浏览器中的js VS NodeJs中的js
)浏览器中的js,就是ECMAScript语法+Web API。
NodeJs中的js,就是ECMAScript语法+Node API。
上图可以看到,语法都是相同的语法(ECMAScript),只不过所在的环境不同,提供的API不同,能干的事就不一样了。图没有列出所有的API,但可以看出,在NodeJS环境中提供的http(http服务相关)。就可以让NodeJs写出服务端程序了。
前端开发 VS 后端开发
前端开发思维 VS 后端开发思维
正如上面所说的,编程语言对于我们学习NodeJs不是障碍,就是ES语法。
首要转换我们的思维,前端是请求数据,然后处理请求结果。后端是接受请求,然后响应请求返回数据。
前后端注重的点,是不一样的,前端注重呈现和交互。后端注重安全和稳定。
前端技术栈 VS 后端技术栈
学习NodeJs是一项大工程,是要学习一整套技术,掌握后端的技术栈,才能真正在工作中使用。
我画一个大概的前后端技术栈对比图:
后端有些技术,是前端用不到的,比如数据库sql。也有些技术,是前后端公共的,比如cookie这种,后端还会注意set-cookie、和session相关的知识点。
相信通过上图,我们能了解NodeJs是什么级别的技术了,不是单指某项技术,而是指Js进行后端开发。
NodeJs知识梳理
启动服务
从总体上观察NodeJs后,再看看细节,第一步就是启动服务:
var http = require("http");
http.createServer(function(request, response) {
// 处理一切
// request接收请求
// response响应请求
}).listen(8888);
NodeJs最主要的也就是这段代码了,服务端就是在接收/响应请求。NodeJs用了一个回调方法,我就可以在其中处理一切了。
路由
要处理不同的请求就写switch就行了。
http.createServer(function(request, response) {
// 从request中获取请求url和method:get/post
switch(url){
case '/api/blog/list':
// 返回博客列表相关代码
break;
case '/api/blog/new':
// 新建博客相关代码
break;
...
case '/api/user/list':
// 返回用户列表相关代码
break;
case '/api/user/new':
// 新建用户相关代码
break;
...
}
}).listen(8888);
一个项目里,要在一个方法里写所有处理请求的代码,不合理,要拆分啊。就有了路由。
我们将不同的请求处理,放到不同的文件里,以blog/user这样的业务逻辑为分割:
// app.js
http.createServer(function(req, res) {
handleBlogRouter(req, res)
handleUserRouter(req, res)
}).listen(8888);
// router/blog.js
export default handleBlogRouter(req, res){
...
switch(url){
case '/api/blog/list':
// 返回博客列表相关代码
break;
case '/api/blog/new':
// 新建博客相关代码
break;
...
}
}
// router/user.js
export default handleBlogRouter(req, res){
...
switch(url){
case '/api/user/list':
// 返回用户列表相关代码
break;
case '/api/user/new':
// 新建用户相关代码
break;
...
}
}
后端的路由,和前端的路由,概念上还是有区别的,前端指页面跳转,一个页面一个路由。后端一个接口地址,指一个路由。
controler
我们继续拆分,让router也单一职责,将业务逻辑也抽离出来:
// router/blog.js
const {
getBlogList,
newBlog,
...
} = require('../controler/blog')
export default handleBlogRouter(req, res){
...
switch(url){
case '/api/blog/list':
const result = getBlogList(id);
res.json(result);
break;
case '/api/blog/new':
const result = newBlog(body);
res.json(result);
break;
...
}
}
这里将生成json、或者生成html等返回数据放在router里,但是业务逻辑,放在controler里。
项目结构
下面基本列一下项目结构,在我们不使用任何框架的情况下,也需要拆分代码。
└─bin #启动HTTP服务
│ www.js
├─logs #日志文件
└─src #项目源码
| controler #放controler,业务逻辑
| model #放model,数据模型,数据库操作
| router #路由相关
| utils #工具类文件
| db #数据库相关 mysql,redis等基本服务封装
| config #项目相关配置
├─app.js 主文件,启动文件
展示项目结构源码地址
我按这个基本的项目结构,写了个小项目,已上传到码云。点击这里查看
在项目中,还可以看到我对请求的主要处理,增强请求对象,包含获取 path 解析、 query解析、cookie设置、session封装、post请求封装。 设置响应对象,如设置返回格式为 JSON。
数据库
首先要选择一个数据库,我选择的是mysql。熟悉数据库工具,使用sql语句。
- 安装数据库,安装数据库可视化客户端
- nodejs连接数据库,将代码写到db文件夹中,接着在model文件夹中写sql语句,接着controler里在调用model中封装的方法。
cookie、session、redis
这三个知识点是有关联的。都是有关状态存储的。
http是无状态的,要想记录状态,就需要用cookie。服务端要记录更多安全的信息,就需要session。更好的利用服务端内存,增加稳定性,就需要redis内存数据库。
最典型的应用就是登录状态的记录。利用cookie记录一个key,利用session存储用户的敏感信息,也可将session存入redis中。
文件操作
服务端需要文件操作,当遇到大文件的时候,还需使用Stream流操作。
最典型的应用的地方,就是日志操作。
安全
服务端必不可少的一块内容就是安全方面的内容,放置xss攻击,sql注入攻击等。
express
理解了服务端开发的方方面面后,就可以上手一个框架了express目前应用的挺广的。
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
可以使用express-generator这样的脚手架,生成的项目,路由日志等模块,都集成好了。
npm install -g express-generator
中间件的使用
框架的核心机制就是插件机制。一个请求过来的时候,一个插件处理一下,交给下一个插件,处理完再交给下一个,逐个处理,最后由负责业务的插件返回响应结果。
这样就将职责拆分开来。让每个插件指处理单一的任务。并且是递进的,如上一个插件封装的操作cookie的相关方法,那下一个插件就可以在request对象中拿到对应的方法,处理业务。
koa2
了解过express后,再看Koa也容易上手了。区别于exress,一个是增加了异步,一个是插件机制变成了洋葱模型。
app.use(async (ctx, next) => {
await next();
var data = await doReadFile();
ctx.response.type = 'text/plain';
ctx.response.body = data;
});
插件的核心机制还是没有变的,也做到了对于一个请求的处理各个职责上的拆分。
koa2也有相应的脚手架
npm install -g koa-generator
nginx反向代理
由于我们的服务器上,即部署了前端也部署了后端,就需要一个反向代理来分配,那些是请求前端资源,哪些是请求后端资源了。
结束语
我只是node的入门阶段,这篇也只是对NodeJs开发的整体做一个大概的介绍。想学好nodeJs,还需多多实战,掌握后端开发的一些概念和技术。在实践中理解它的工作机制及原理。