Koa2 是 Express 团队基于 ES7 编写的 Web 框架,在此框架中,Koa2 利用 Promise 和 async 实现异步方法,在 Koa 中最显著的特点就是将原本内置在 Express 中的已经封装好的中间件分别封装到了不同的模块中,所以 Koa 与 Express 相比是更轻量级的
在使用 Koa2 之前,必须先下载 Koa2,示例如下:
npm install koa --save
默认情况下,若未特别说明版本,那么下载的就是 Koa2.X
在 Koa2 下载完成之后,就可以非常快速地创建一个服务器应用程序,示例如下:
// 1. 导入 Koa
const Koa = require('koa');
// 2. 创建 koa 实例
const app = new Koa();
// 利用 koa 实例响应请求
app.use(ctx => {
ctx.body = 'Hello Koa!';
})
// 3. 利用 koa 实例监听端口
app.listen(3000);
上述示例中,系统将自动向 koa 实例 use 方法中的回调函数传入 ctx 实例,此实例中包含了请求实例 request 和响应实例 response,也包含了 Koa 补充的属性和方法
由于 Koa2 将处理静态资源的中间件封装到了 koa-static 模块中,所以在使用之前必须先下载此模块,示例如下:
npm install koa-static --save
在下载之后就可以利用此模块处理静态资源,示例如下:
// 导入 koa-static
const serve = require('koa-static');
// 利用 koa-static 模块处理静态资源
app.use(serve('public'));
上述示例中,参数 public 为静态资源所在的目录
由于 Koa2 将处理动态资源的中间件封装到了 koa-views 模块中,所以在使用之前必须先下载此模块,示例如下:
npm install koa-views --save
在下载之后就可以利用此模块处理动态资源,示例如下:
// 导入 koa-views
const views = require('koa-views');
// 利用 koa-views 模块处理动态资源
app.use(views('views', {extension: 'ejs'}));
// 响应动态资源时渲染网页
app.use(async ctx => {
await ctx.render('login', {username: 'Reyn Morales', password: 1024});
});
上述示例中,参数 views 为动态资源所在的目录,extension 属性说明渲染动态网页的模板引擎,类似于在 Express 中,动态资源的扩展名必须为模板引擎的名称
由于 Koa2 将处理路由的中间件封装到了 koa-router 模块中,所以在使用之前必须先下载此模块,示例如下:
npm install koa-router --save
在下载之后就可以利用此模块处理路由,示例如下:
// 导入 koa-router
const Router = require('koa-router');
// 创建 Router 实例
const router = new Router();
// 路由前缀
router.prefix('/api/user');
// get 请求
router.get('/info', (ctx, next) => {
ctx.body = {
username: 'Reyn Morales',
age: 21,
gender: 'Male'
}
});
// post 请求
router.post('/login', (ctx, next) => {
ctx.body = 'Login Success';
});
// 导出 router 实例
module.exports = router;
上述示例中,通过 router 的 prefix 实例方法可以注册路由前缀,之后处理请求时可以省略此前缀,此外,ctx 实例的 body 方法可以为字符串或实例,如果被赋值为字符串,那么等价于 res.writeHead 和 res.end,如果被赋值为实例,那么等价于 res.writeHead 和 res.json
// 导入 router 实例
const userRouter = require('./router/user');
app
.use(userRouter.routes()) // 启动路由
.use(userRouter.allowedMethods()); // 响应头
示例如下:
router.get('/info', (ctx, next) => {
/* 以实例的形式 */
console.log(ctx.request.query);
/* 以字符串的形式 */
console.log(ctx.request.querystring);
});
示例如下:
router.get('/register/:username/:password', (ctx, next) => {
console.log(ctx.params);
});
必须注意的是,在客户端发送请求时路由中必须以
/
字符分隔所有的参数
由于 Koa2 将处理 post 请求参数的中间件封装到了 koa-bodyparser 模块中,所以在使用之前必须先下载此模块,示例如下:
npm install koa-bodyparser --save
在下载之后就可以利用此模块处理 post 请求参数,示例如下:
// 导入 koa-bodyparser
const bodyParser = require('koa-bodyparser');
// 利用 koa-bodyparser 模块处理 post 请求参数
app.use(bodyParser());
// 尝试获取 post 请求参数
router.post('/login', (ctx, next) => {
console.log(ctx.request.body);
});
在 Koa2 中不用导入任何模块即可以通过 ctx 实例操作 Cookie
示例如下:
router.get('/register/:username/:password', (ctx, next) => {
ctx.cookies.set('user', ctx.params.username, {
path: '/',
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000
});
ctx.body = 'Register Success';
});
必须注意的是,在添加 Cookie 时不能将中文字符作为 value 中存储到客户端中,此时可以将中文字符先转换为 base64 的字符串,然后将此字符串作为 value 存储到 Cookie 中,此处不再详细说明
示例如下:
router.get('/info', (ctx, next) => {
console.log(ctx.cookies.get('user'));
ctx.body = {
username: 'Reyn Morales',
age: 21,
gender: 'Male'
}
});
由于 Koa2 将处理错误的中间件封装到了 koa-onerror 模块中,所以在使用之前必须先下载此模块,示例如下:
npm install koa-onerror --save
在下载之后就可以利用此模块处理错误,示例如下:
// 导入 koa-onerror
const onerror = require('koa-onerror');
// 启动 onerror
onerror(app);
// 错误处理
app.use((err, ctx) => {
console.log(err.status, err.message);
ctx.body = err.message;
});
上述示例中,err 实例的 status 属性为错误状态码,而 message 属性为错误信息
koa-generator 是一个 Koa 项目的脚手架工具,通过此工具可以快速生成一个功能齐全的项目框架,步骤如下:
下载 koa-generator
npm install koa-generator -g
利用 koa2 命令创建一个 koa2 项目
koa2 <ProjectName>
利用 cd 命令切换至项目目录下
cd <ProjectName>
通过 npm 命令下载项目所依赖的包
npm install
默认情况下,Cookie 不能跨域访问,此时可以通过 Nginx 反向代理实现 Cookie 的跨域访问
在 URL 中,如果协议、域名(不同级别)或端口号中任何一个或若干个不同,即为跨域
正向代理即顺着请求的方向代理,例如,通常情况下我们不能访问谷歌服务器,而通过一台海外服务器可以访问谷歌,那么我们可以访问此海外服务器,此海外服务器访问谷歌,从而实现访问谷歌,此时,这台海外服务器即为正向代理服务器,在正向代理中,代理服务器为用户服务,对于谷歌来说,并不知道是哪一个用户访问,只知道有一台服务器访问了自己,用途如下:
反向代理和正向代理相反,在反向代理中,代理服务器为服务器服务,对于用户来说,并不知道自己真正访问的服务器是谁,只知道自己访问了一台服务器,用途如下:
反向代理服务器可以根据用户的路由地址将请求分发到不同的服务器,例如,如果用户访问根路由,那么将请求发送至前端服务器,如果用户访问接口路由,那么将请求发送至后端服务器,如果在后端添加或访问 Cookie,那么最终都是通过代理服务器向浏览器中添加或访问,因此解决了 Cookie 的跨域问题
通常情况下,我们可以利用 Nginx 实现反向代理,在 Nginx 的配置文件 /conf/nginx.conf
中可以编写相关的代理信息,如下所示
worker_processes 4;
location / {
proxy_pass <front-end-server-url>;
}
location /api {
proxy_pass <back-end-server-url>;
proxy_set_header Host $host;
}
通过 http-server 模块可以快速以服务器的形式启动一个 Web 前端项目
在考虑将 Node 项目上线时,必须考虑如下问题:
此时可以通过 PM2 解决上述问题
在使用 PM2 之前,必须先下载,示例如下:
npm install pm2 -g
通过 version 选项可以查看 PM2 的版本,示例如下:
pm2 --version
通过如下指令可以启动一个 Node 程序:
pm2 start <FileName>
示例如下:
pm2 start app.js
PM2 的常用指令如下所示:
指令 | 含义 |
---|---|
pm2 start <appName/appId> | 启动应用程序 |
pm2 list | 列出启动的所有应用程序 |
pm2 restart <appName/appId> | 重启应用程序 |
pm2 info <appName/appId> | 查看应用程序详细信息 |
pm2 log <appName/appId> | 显示指定应用程序的日志 |
pm2 monit <appName/appId> | 监控应用程序 |
pm2 stop <appName/appId> | 停止应用程序 |
pm2 delete <appName/appId> | 关闭并删除所有应用 |
默认情况下,如果程序出现错误或抛出异常,那么 PM2 将自动重启 Node 程序以实现服务的稳定性
如果通过 PM2 启动 Node 应用程序,在程序中,如果利用 console.log 方法输出信息,那么将自动被保存为自定义日志,如果利用 console.error 方法输出信息,那么将自动被保存为错误日志
实际上,也可以通过 PM2 的配置文件启动 Node 应用程序,通过配置文件可以自行配置项目名称和日志记录等相关信息,示例如下:
{
"apps": {
"name": "MyApp",
"script": "app.js",
"watch": true,
"ignore_watch": [
"node_modules",
"logs"
],
"error_file": "logs/err.log",
"out_file": "logs/custom.log",
"log_date_format": "YYYY-MM-DD HH:mm:ss"
}
}
上述示例中,name 属性表示项目名称,script 属性表示入口文件,watch 属性表示是否开启监视,ignore_watch 属性表示省略监视哪些文件,error_file 属性表示错误日志记录位置,out_file 属性表示自定义日志记录位置,log_data_format 属性表示日志记录时的时间格式,此外,必须注意的是,PM2 配置文件的名称为 pm2.config.json
在 PM2 的配置文件中可以通过 instances 属性实现负载均衡,示例如下:
{
"apps": {
"name": "MyApp",
"script": "app.js",
"watch": true,
"ignore_watch": [
"node_modules",
"logs"
],
"error_file": "logs/err.log",
"out_file": "logs/custom.log",
"log_date_format": "YYYY-MM-DD HH:mm:ss",
"instances": 4
}
}
必须注意的是,instances 属性的取值不能超过服务器的 CPU 核数,此外,在修改了配置文件后,必须关闭项目后再次重启才能生效