安装
1
|
npm install --save koa
|
创建 app.js
:
1
|
const Koa = require('koa')
|
Koa 中间件
中间件就是匹配路由前和匹配路由后做的一系列操作。中间件的功能包括:
- 修改请求和响应对象
- 终止请求和响应循环
- 调用堆栈中的下一个中间件
中间件按照功能可以分为:
- 应用级中间件
- 路由中间件
- 错误处理中间件
- 第三方中间件
应用级中间件
应用级中间件,我觉得可以叫做全局中间件,就是所有请求都要经过的。举例:对于每一个请求,打印它的请求时间:
1
|
const Koa = require('koa')
|
类比 redux 中的中间件,中间件通过 use
注册,内部保存在一个中间件的数组中。可以通过调用 next()
方法执行下一个中间件。如果不调用,那么后面的中间件都不会继续执行。
路由级中间件
路由级中间件可以使一个请求匹配多个路由:
1
|
const Koa = require('koa')
|
不同于应用级中间件,路由级中间件只针对路由。可以大概猜测出,应用级中间件中的 next
是 koa 提供的,而路由级中间件的 next
方法应该是 koa-router 提供的。
错误处理中间件
其实就是一个应用级中间件。错误处理用在没有匹配任何路由,返回一个 404 页面:
1
|
const Koa = require('koa')
|
利用这种方式可以做消息转发
koa 路由中间件
安装:
1
|
npm install --save koa-router
|
静态路由
示例
1
|
const Koa = require('koa')
|
获取 get 传值
1
|
router.get('/news', async (ctx) => {
|
获取 post 传值
安装 koa-bodyparser
1
|
npm install --save koa-bodyparser
|
1
|
const Koa = require('koa')
|
get 和 post 都支持
如果一个请求,既要支持 get 又要支持 post 也是可以的,可以使用 .all
方法:
1
|
router.all('/:pid', async (ctx) => {
|
动态路由
静态路由要求路径完全匹配,动态路由可以前部匹配,后部可以动态获取。koa 中通过 :
作为动态路由的标识:
1
|
// 动态路由匹配 /news/xxxx
|
动态路由可以匹配多个值。如 /news/:aid/:cid
设置 Cookie 和 Session
设置 cookie
设置 cookie
1
|
router.get('/', async (ctx) => {
|
获取 cookie
1
|
router.get('/', async (ctx) => {
|
如果客户端需要拿到 cookie,那么必须设置 httpOnly 为 false
设置 Session
session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而
session 保存在服务器上。
Session 的工作流程
当浏览器访问服务器并发送第一次请求时,服务器端会创建一个 session 对象,生
成一个类似于 key,value 的键值对, 然后将 key(cookie)返回到浏览器(客户)端,浏览
器下次再访问时,携带 key(cookie),找到对应的 session(value)。 客户的信息都保存
在 session 中。
设置 Session
1
|
npm install --save koa-session
|
使用:
1
|
// 引入
|
koa-session
的原理就是在内存中生成一个 session 的散列表。每次生成一个随机的字符串,并将其作为 cookie 下发给客户端,key 对应于 config 中的 key。设置的 app.keys
应该就是加密用的秘钥。
当 session 量比较大的时候,就需要考虑通过使用外部存储的方式进行存储。比方说 mysql,redis 等
Session 和 Cookie 的区别
- cookie 数据存放在客户的浏览器上,session 数据放在服务器上。
- cookie 会暴露用户的信息,所以使用 session,只在 cookie 中保存一个 id,每次请求通过这个 id 从 session 散列表中获取相应的信息。
- 单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie。
访问静态文件
如果不想使用模板渲染或者 nuxt.js 这种服务端渲染框架。可以尝试直接访问 vue 生成的 dist 文件。
生成 Vue 的 dist 目录
通过 vue-cli 生成 Vue 项目,通过 npm run build
生成 dist 目录,把 dist 目录整个拷贝到 koa 所在目录下:
访问静态文件
访问静态文件需要使用相关中间件 koa-static
:
1
|
const Koa = require('koa')
|
此时当你访问 localhost:3000
的时候,koa 就会将 dist/index.html
返回显示。
如果同时使用了路由中间件,需要把资源文件的中间件先于路由中间件注册。否则会被路由拦截
路由模块化
把所有路由放在一个文件中显然是不好维护的,因此需要针对路由进行子路由拆分。
实现
创建子路由
首先创建 routes 文件夹,创建子路由文件,比如命名为 admin.js。在其中添加子路由:
1
|
// 在 /routes/admin.js 目录下
|
引入子路由
1
|
// app.js
|
这样以下请求就会映射到相应子路由中:
1
|
http://localhost:3000/admin
|
实践
node 自动重启
开发的时候每次修改都要手动重新 run 一次 node 会非常的麻烦。因此需要一个能自动重启的库的帮助。这个库就是 nodemon:
1
|
npm install -g nodemon
|
全局安装 nodemon,然后启动的时候不要通过 node 了,而是 nodemon:
1
|
nodemon app.js
|
文件操作
使用 node 提供的 fs 操作文件比较复杂,尤其是使用 koa 的时候本生不支持 promise 写法。
fs-extra 是一个比较完善的文件操作封装库:
1
|
npm install --save fs-extra
|
使用起来也和 fs 无异。下面例子中读取本地的 json 文件并返回:
1
|
const fse = require('fs-extra')
|
发送请求
我们使用 koa 接收客户端请求。但是很多时候,我们需要对请求做转发。因此,需要使用 nodejs 发送请求。
发送请求可以使用库 request-promise。它是 request 的 promise 版本:
1
|
npm install --save request-promise
|
请求方式很简单:
1
|
app.use(async (ctx, next) => {
|
要注意, await
中发生的 error 需要通过 try…catch 捕获。
设置环境变量
node 中的环境变量在 process.env
中保存,使用库 cross-env
可以方便设置兼容 windows 的环境变量:
1
|
npm install --save-dev cross-env
|
package.json 中设置环境变量:
1
|
{
|
NODE_ENV
环境变量将由 cross-env 设置。打印 process.env.NODE_ENV === 'production'
为 true
允许跨域
跨域的请求需要借助第三方的库 koa-cors
进行允许跨域设置:
1
|
npm install koa-cors
|
使用:
1
|
app.use(cors({
|
其中 origin 字段对应于 access-control-allow-origin
,通过它设置哪些站点发起哪些请求可以进行跨域。上面🌰表示,请求路径为 /cors
的这个请求可以进行跨域,但是不能获取 cookie 信息,而 http://localhost:3000
这个域名下的所有请求都可以进行跨域,且可以获取 cookie 信息,是受信的站点。
如果设置了 access-control-allow-origin
为 *
,那么就是允许跨域了。但是跨域的客户端请求,无法携带该域名下的 cookie 信息给服务端。
必须设置 access-control-allow-origin
为一个特定的域名,而不是 *
。这样 Access-Control-Allow-Credentials
才会被默认置位 true,才可以跨域使用 cookie。
所以这是一个三级保证。没有 *,那么无法发出请求,没有特定的域名,没有发送带 cookie 的请求。
连接 Mysql
Nodejs 连接 Mysql 需要 install 相关的库:
1
|
npm install --save mysql
|
基本使用:
1
|
const mysql = require('mysql')
|
防止 sql 注入
sql 如果是通过字符串拼接的方式注入的参数,那么容易引起 sql 注入。Nodejs 中的 mysql 库引入了 escape
方法,会对参数进行转义:
1
|
select id from User where username = ${escape(username)}
|
redis
redis 是一种内存存储,可以配合 mysql 进行频繁操作的数据的存储。
安装 redis
安装
1
|
brew install redis
|
启动 server
1
|
redis-server
|
启动 client
1
|
redis-client
|
存取值
1
|
# 设置键值对
|
使用 redis
安装 redis nodejs 模块
1
|
npm install redis --save
|
node 中使用
1
|
const redis = require('redis')
|
PM2
- 进程守护,系统奔溃自动重启
- 启动多进程,充分利用 CPU 和内存
- 自带日志记录
下载
1
|
npm install pm2 -g
|
启动
开发环境下使用 nodemon
,线上环境可以使用 pm2
:
1
|
pm2 start app.js
|
常用命令
1
|
# 查看进程列表
|
命令行
node 写脚本需要配合 shell 语法,shelljs
是一个封装的很晚上的库