Koa2 Boilerplate

这是我整理的一个 koa2 + es7 的一个最佳实践,用了一些新的 Feature,完成了全部流程,从 request 到 service 和 DB(Sequlize)到 response。


Features

koa2 & koa-router

koa 相对于 express 更吸引开发者的地方莫过于 U 型 Middleware 机制。

Babel

目前 node v6 已经支持了绝大多数新的语法,http://node.green/

目前用下来只有两个 feature,就是 asyncFuncation 和 module,所以在配置项中,只需要开启这两项就够了。async 会被编译为 generater。

1
2
3
4
{
"presets": ["es2017"],
"sourceMaps": "both"
}

AsyncFuncation

通过 babel 来实现了 async-await (为了 async 的美可以做出任何牺牲)。

Module

ES 6 中模块化有一些显著的变化,像 import/export,具体见

标准已经制定:修改文件名后缀为 .mjs 但目前仍需要 babel 来转。

DI Container

因为没有模块,所以大量的引用散落在各处,一量修改,真的是痛不堪言。

DI 可以统一管理这些依赖,只需要修改一处,当然最大的好处莫过于解耦,便于测试。

这里用的是 Awilix

Environment

通过 yenv 来实现环境变量管理。

Sequlize

我们在项目中大量的使用了 Sequlize,也吐槽了很多,这里只是一个最简单的结合示例。


Directory structure

一般通过 node 创建的 web 项目,通用的作法是将源码等放在一个 src 的目录下,这样的好处是为了方便编译,感谢 babel,可以提前享受 ES 新语法。

后端项目也有一些这样的实践,但这里并没有采用,原因是随着 node 对标准的支持,在不久的将来,我们线上的代码是不再需要编译的。可以像 rails 一下直接运行(好期待那天)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.
├── app
│   ├── apis
│   ├── beapis
│   ├── models
│   ├── services
│   └── validators
├── bin
│   ├── _babel.js
│   └── server.js
├── config
│   ├── application.yml
│   ├── database.yml
│   └── redis.yml.example
├── db
├── lib
│   ├── createContainer.js
│   ├── createServer.js
│   └── middleware
├── .babelrc
├── Dockerfile
├── yarn.lock
└── package.json

当然目前还是需要编译的,这样就不需要在服务器上跑 babel-runtime。dist 是编译后的目录,通过 npm 对具体目录做了一些单独的编译。

  • app: 项目主要的业务逻辑代码。
    • api: 本层主要处理到达的请求,将参数做整理,然后交由 service 层。
    • services: 服务层从 repo 层取数据,然后拼接加工,最后返回 api 层。
    • model: 项目的 models。
  • bin: babel 需要一个启动文件。
  • config: 环境变量配置目录。
  • db: 数据库的一些资源。
  • dist: 编译后的文件。
  • lib: 一些系统类库,处理环境变量。和工具类。
    • middleware: middleware。
  • test: 测试用例。


npm run scripts

这里定义了一些常用的启动命令:

  • start: Used by the production environment to start the app. This will run a compiled version, so you need to execute build first.
  • build: Runs the babel CLI to compile the app. Files are emitted to dist/.
  • dev: Runs the app in development mode - uses babel-register to compile on-the-fly. Also uses nodemon to automatically restart when stuff changes.
  • debug: Runs the app in development mode with icebug (a combo of nodemon + node-inspector).
  • test: Runs mocha tests.
  • test-watch: Runs mocha tests in watch-mode.
  • lint: Lints the code in src and test with eslint.
  • lint-watch: Same as above, in watch-mode.

Tip: to pass additional arguments to the actual CLI’s being called, do it like in this example:

1
npm run test -- --debug