Koa入门教程[5]-升级为Koa2

先来翻译一波 官方的 migration 指南:

从 Koa v1.x 迁移到 v2.x

新的中间件函数签名

Koa v2 引入了一个新的中间件签名

老的中间件签名方式 (v1.x) 将在 v3 版本删除

新的 middleware 签名如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 用async箭头函数
app.use(async (ctx, next) => {
try {
await next(); // next不再是generator迭代器,而是一个asycn函数了
} catch (err) {
ctx.body = { message: err.message };
ctx.status = err.status || 500;
}
});

app.use(async (ctx) => {
const user = await User.getById(this.session.userid); // 用await代替yield
ctx.body = user; //用ctx变量代替this
});

你不是只能用 async 函数-你只需要保证传递一个返回 promise 的函数
一个普通返回 promise 的函数照样可以工作。

这个中间件函数签名改成了传入一个严格的 ctx 参数 ( Context 对象),而不是用 this 来访问当前请求上下文. 这个改变使得 koa 更能兼容 es6 箭头函数捕获 this.

在 v2.x 中使用 v1.x 的中间件

Koa v2.x 在调用 app.use 的时候可以兼容 generator 的 middleware,它使用koa-convert.来干这件事。
然而还是建议你赶紧迁移这些 v1 的中间件。

1
2
3
4
5
6
7
// Koa会转换这种generator中间件
app.use(function* (next) {
const start = Date.now();
yield next;
const ms = Date.now() - start;
console.log(`${this.method} ${this.url} - ${ms}ms`);
});

你也可以手工转换自己的中间件,这样 app.use 里面就不会再转换了。

1
2
3
4
5
6
7
8
9
10
const convert = require("koa-convert");

app.use(
convert(function* (next) {
const start = Date.now();
yield next;
const ms = Date.now() - start;
console.log(`${this.method} ${this.url} - ${ms}ms`);
})
);

升级中间件

要想升级中间件,你必须把你的中间件换成这种箭头函数的 async 函数。

1
2
3
4
5
app.use(async (ctx, next) => {
const user = await Users.getById(this.session.user_id);
await next();
ctx.body = { message: "some message" };
});

升级中间件需要一些工作量,一个比较好的迁移路径是 一个个的来

  1. 先用 koa-convert 包裹你现在的 v1 版本的中间件
  2. 测试是否正常
  3. 执行npm outdated 看看你依赖的第三方中间件有哪些过时了
  4. 按照上面讲的升级你的中间件,然后移除掉 koa-convert 的包裹
  5. 测试是否正常
  6. 不断重复 1-5 升级所有中间件

升级你的代码

迁移到 Koa v2 你可能也要升级自己的业务代码:

  • 在任何异步的地方都返回 promise!
  • 不要再用 yield*
  • 不要再用 yield {} or yield [].
    • yield [] 换成 yield Promise.all([])
    • yield {} 换成 yield Bluebird.props({})

你也可以重构你的中间件以外的逻辑代码函数,例如写成接收 ctx 上下文参数的这种:
function* someLogic(ctx) {}
这样在你 v1 的 koa 的中间件里这样调用:
const result = yield someLogic(this).
先放弃使用 this 可以帮助你未来迁移到 v2 里面不用 this 的情况。

Application 构造函数必须使用 new 运算符

在 v1.x 里,Application 构造函数可以直接调用来实例化,例如:

1
2
var koa = require("koa");
var app = (module.exports = koa());

v2.x 里面构造函数用了 es6 的 class,必须使用 new 关键字

1
2
var koa = require("koa");
var app = (module.exports = new koa());

ENV 指定日志行为的环境变量被移除了

错误处理时对 test 环境变量的严格检查被移除了

依赖变化

  • co已经不是内置在 koa 里面了(因为不需要了)。如果你需要,则需要自己引入。
  • composition is 这个 compose 中间件的函数已经废弃了。Koa2 用的是 koa-compose

v1.x 的支持

The v1.x branch is still supported but should not receive feature updates. Except for this migration
guide, documentation will target the latest version.
v1.x 分支还会继续支持,但不会再增加新的 feature。除了这个迁移文档,默认的官方文档都指向 v2 的

帮助

如果你遇到迁移的其他问题,可以提交 pull request

todo-list 应用的升级

// TODO