Koa 脚手架
koa-generator 是用于生成 Koa 项目骨架的生成器,虽然比较精简,但它的结构十分清晰,足以满足一般的开发需求。
与 express-generator 的功能对比
express-generator 提供的功能如下
- 生成项目骨架,集成必要的中间件。
- 约定目录结构。
- 支持 css 预处理器。
koa-generator 提供的功能如下
- 生成项目的骨架,集成必要的中间件。
- 约定目录结构(和 express-generator 约定的结构一模一样)
两个生成器共同支持的项目骨架描述如下
- app.js 为入口
- bin/www 为启动入口
- 支持静态服务器,即 publish 目录
- 支持 routes 目录
- 支持 views 视图目录
- 默认将 Pug (之前的名字是 Jade)作为模板引擎。
1.2.1 安装 Koa 生成器
npm install -g koa-generator
koa-generator 支持 v1 和 v2 ,安装后分别使用 koa 和 koa2 命令创建 Koa 项目模板,以 koa2 为例。
1.2.2 创建 Hello world
koa2 helloworld
1.2.3 目录解析
使用 koa-generator 生成的目录结构如下:
.
├── app.js
├── bin
| └── www
├── directoryList.md
├── out.txt
├── package.json
├── public
| ├── images
| ├── javascripts
| └── stylesheets
├── routes
| ├── index.js
| └── users.js
└── views
├── error.pug
├── index.pug
└── layout.pug
下面会对以上文件作用和文件的内容做简单的介绍
package.json
package.json 是 Node.js 模块定义的核心配置文件,接触新项目的第一件事就是打开该文件了解模块的各个属性。比如名称,版本,依赖模块,开发方式等。
package.json 文件里包含了 4 个 npm script 脚本,分别介绍如下:
- npm start 是开发阶段使用的脚本,使用时代码发生变动,需要重启 Node.js 进程。
- npm run dev 也是开发阶段使用的脚本,使用时代码会发生变动, nodemon 会自动启动 Node.js 进程。
- npm run prd 是产品环境使用的脚本,通过 pm2 来启动工程,默认按照 CPU 核数来启动对应的进程数,是目前最流行的方式。
- test 只会打印未实现日志,和 Express 里的用法是一样的。
入口文件 bin/www
入口文件的核心代码如下:
const server = http.createServer(app.callback())
server.listen(port)
server.on('error', onError);
server.on('listening', onListening);
这里唯一和 Express 不同的是,Koa 里的 app.callback() 返回的是 function(req, res){},所以想在 http.createServer 里启动 Koa,就必须将 app 修改为 app.callback().
核心文件 app.js
app.js 是 Koa 的核心文件,主要包含 4 个部分,分别如下
- 中间件
- 路由
- 静态服务
- 视图
这里注意,中间件按照加载顺序执行,下面是 app.js 里包含的中间件的名称,用途(按照加载顺序排列)。
中间件名称 | 用途 | 加载顺序 |
---|---|---|
bodyparser | 解析 Post 类 HTTP 动词的 body 内容,加上 bodyparser 后就可以处理所有请求了 | 1 |
json | 更好的支持 JSON | 2 |
logger | 开发阶段的日志 | 3 |
koa-static | 提供 HTTP 静态托管服务 | 4 |
koa-views | 视图渲染,支持模板引擎 | 5 |
自定义的 logger 中间件 | 记录日志 | 6 |
路由位于 routes 目录下
路由支持返回 视图渲染,JSON API 和字符串
- 视图渲染
router.get('/', async(ctx, next) => {
await ctx.render('index', {
title: 'Hello Koa 2!'
})
})
- JSON API
router.get('/json', async (ctx, next) => {
ctx.body = {a:1}
})
- 字符串
router.get('/string', async(ctx, next) => {
ctx.body = 'koa2 string'
})
赋予 ctx.body 不同类型的值时会返回不同的结果;值得注意的是,ctx.render 是 koa-views 中间件绑定到 ctx上的,原本 ctx 上是没有 render 函数的。
静态服务位于 public 目录下
静态服务主要用于存放静态资源,比如 HTML,CSS,JS 文件等,但是值得注意的是,静态服务是方便开发存在的,实际项目处理时,一般将静态文件存放在 CDN 服务器上。
public目录是为了方便开发而存在的,一般真正的项目有如下三类:
- 纯 API 项目,不需要 public 目录。
- 纯前后端分离项目,后端不需要 public 目录,前端需要
- 需要 public 目录的项目,但会将 public 目录的内容发布到 cdn 上。
tip: 注意,不要把 static 中间件放到 Koa 的全局中间件上(如果对于每个请求都需要判断一次是不是静态资源,会影响 QPS),最好结合 koa-router 来处理,按需挂在,上代码。
router.get('/public/', async (ctx, next) => {
ctx.url = path.basename(ctx.url)
await next()
}, staticServer(resolve('./public'), {gzip: true}))
视图位于 views 目录下
Koa 多采用 Pug 作为模板,使用时可根据需要自行选择。
1.2.4 Koa v2 中间件的写法
Koa 支持三种中间件写法,功能是一样的
- async 函数优先级最高,最简单易懂。
- Promise 其次。await 结合 Promise 是非常常见的,而且利用 Promise的特性是刚需,比如,通过 Promise.race 和 Promise.all 等实现并发可以在某种程度上弥补 async 函数的不足。
- Generator 主要在 Koa v1 中使用,ES6 Generator 风格的中间件非常常见。使用时可以通过 co 库来调用 ES6 Generator,由于 co 的返回值是 Promise,所以相当于重复了 await + Promise 的用法。
1.2.5 路由
koa-router 中间件提供了路由机制,使用时进一步学习。
1.2.6 切换视图模板引擎
使用以下命令可以在创建项目时切换模板
koa2 -e hellowrold -ejs
下面以切换 react 模板引擎为例,演示模板的切换过程
- 安装对应的模板引擎模块:npm install --save react。
- 修改 app.js 里与 koa-views 相关的配置,将 extension 设置为 react,代码如下:
app.use(views(__dirname + './views'), {
extension: 'react'
})
1.2.7 Koa 代码调试
各个编辑器都提供了调试功能,根据编辑器自行调试即可。