Koa v1.2.1で書かれたアプリケーションをKoa v2.0.0にアップデートしたのでそのログ的なものです。
v1からの大きな変更点として、middlewareのインターフェースがgenerator functionからasync/awaitへと変わっています。
環境の用意
Koa v2ではasync/awaitが使える環境が必要となります。現状Node.jsでasync/awaitを使うためには主に
- Node.js v7系を使い
--harmony-async-await
オプションをつけて起動 - Babelでトランスパイル&polyfill
という二種類の方法がありますが、ここでは後者のBabelを使う方法で進めていきます。
$ npm install babel-polyfill babel-plugin-transform-async-to-generator
既にクライアント側でBabelを使用していて、presetやpluginsの設定を分けたい場合はenvを設定します。
{
"env": {
"client": {
"presets": [ "es2015", "react" ],
"plugins": [
"add-module-exports",
"transform-class-properties",
"transform-object-rest-spread",
"transform-export-extensions"
]
},
"server": {
"presets": [ "es2015" ],
"plugins": [
"transform-async-to-generator"
]
}
}
}
BABEL_ENV
を指定した上でbabel-nodeを使って動かします。
"start": "BABEL_ENV=server babel-node index.js"
なおパフォーマンスなどの問題から、productionではbabel-nodeではなくフロントのコード同様トランスパイルしたものを使用することが推奨されています。
"build": "BABEL_ENV=server babel index.js --out-file bundle.js",
"start:production": "node bundle.js"
Koa v2のインストール
$ npm i koa@2
v2ではクラスコンストラクタを返すようになったので対応します。
import koa from 'koa';
const app = koa();
import Koa from 'koa';
const app = new Koa();
migration
generator -> async/await or Promise
generator functionをasync/awaitに書き換えていきます。
app.use(function *(next) {
try {
yield next;
} catch (err) {
if (401 == err.status) {
this.status = 401;
this.set('WWW-Authenticate', 'Basic');
this.body = 'authorization required';
} else {
this.throw(err);
}
}
});
app.use(async (ctx, next) => {
try {
await next;
} catch (err) {
if (401 == err.status) {
ctx.status = 401;
ctx.set('WWW-Authenticate', 'Basic');
ctx.body = 'authorization required';
} else {
ctx.throw(err);
}
}
});
あるいはPromiseで書くこともできます。
app.use((ctx, next) => {
next().catch((err) => {
if (401 == err.status) {
ctx.status = 401;
ctx.set('WWW-Authenticate', 'Basic');
ctx.body = 'authorization required';
} else {
ctx.throw(err);
}
});
});
koa-convert
未対応のmiddlewareは、koa-convertを使ってgenerator functionをPromiseを使用したものに変換することができます。
import logger from 'koa-logger';
import serve from 'koa-static';
app.use(logger());
app.use(serve('.'));
import logger from 'koa-logger';
import serve from 'koa-static';
import convert from 'koa-convert';
app.use(convert(logger()));
app.use(convert(serve('.')));
さいごに
とりあえずconvertで囲ってしまえばどうにかなるのは楽でいいですね。
async/awaitのためだけにサーバーサイドでBabelを使用するのは、ビルドプロセスも複雑になるし正直あまり筋のいい方法とは言えないのでNode.js v7入れられるならそちらの方が良いでしょう。
ちなみにKoa v2の正式リリースはNode.js上でstableなasync/awaitが実装されたらとのことなので、Node.js v8が出る頃には出そうですね
FYI: フレームワークDL数比較
Koaよりhapi,restifyの方が多いようです。。。1
last month(2016/12/17) | |
---|---|
express | 7,942,528 |
restify | 258,329 |
hapi | 246,358 |
Koa | 156,030 |
sails | 67,201 |
Trails | 10,423 |
Node.js Advent Calendar 2016 17日目の記事でした。
-
Meteorはnpmで入らないためDL数判らず ↩