trunk-logo-white

最新消息

升級 koa 2.0 及 babel 設置與注意事項

Share This Post

分享在 facebook
分享在 linkedin
分享在 twitter
分享在 email

koa 是什麼這邊就不多作解釋,koa 1.0 跟 koa 2.0 升級基本上沒有想像中的簡單,年前進行了一次,以失敗告吹,今年又進行了一次,總算革命成功。

其中 koa 1.0 跟 2.0 最大的差異就是原本使用 function*/yield 改為使用 async/await 因此我們需要 babel 的幫忙以便讓我們使用該特性。

babel 設置

koa 2.0 可以搭配最新的 babal 我們需要下面相關套件

    "babel-core": "^6.4.0",
    "babel-polyfill": "^6.3.14",
    "babel-preset-es2015": "^6.3.13",
    "babel-preset-stage-0": "^6.3.13",

安裝相關套件後,我們就可以在啟動 koa 之前設置

require("babel-core/register")({
     presets: ['es2015', 'stage-0']
});
require("babel-polyfill");
module.exports = require('./koa.js');

如此就可以搭配 koa 使用 async/await,接著因為新舊的差異,第一個影響到的就是 koa 相關的 middleware package,畢竟不是所有的套件都有跟著升版到新的機制,這也是升級最痛苦的地方,還好有 koa-convert

koa-convert 將舊版轉換為新版處理機制

使用方法如下:

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

若是 middleware 可以這樣用

import responseTime from 'koa-response-time';
import convert from 'koa-convert';
app.use(convert(responseTime()));

過渡時期可以讓尚未升級的套件運作正常,接著升級後程式碼會有幾個寫法上的改變

語法變更

function*/yield change to async/await

看 diff 最快 🙂

Babel v6.4 Requires semicolons after class properties

https://github.com/feross/standard/issues/372

新的 Babel class 的 properties 強制需要 ;

await* 廢用

await* 之 *Promise.all 取代。

export default 使用 require 多了一層 default

另外一個雷,在 babel 6 若你用 export default 務必使用 import,若使用 require 將會多一層 default。

這個特性會造成升級後相關載入失效,要注意。

詳細解釋請參考:
https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0#.k4730osf2

懶人包:

Option 1: require with default

// add.js
export default (x, y) => x + y
// bar.js
const three = require('./add').default(1, 2

Option 2: ES6 modules 100%

// add.js
export default (x, y) => x + y
// bar.js
import add from './add'
const three = add(1, 2)

Option 3: CommonJS 100%

// add.js
module.exports = (x, y) => x + y
// bar.js
const three = require('./add')(1, 2)

若你想要在 babel6 保持 babel5 的 export 的特性可以參考

http://stackoverflow.com/a/33725725

之所以 babel6 規格會這樣要求,主要是因為 Tree-shaking 的特性,所以長遠來看,建議是使用 Option 2: ES6 modules 100% 的選項。

詭異的 this

有 this: 使用 async + fat arrow 但沒定義函式參數

export default class Test {
  hello = async () => {
    console.log(this); // 這裡有東西
    let hello = 'yes!';
    return {hello};
  }
}
describe("Test this", () => {
  it.only("test", async done => {
    try {
      let test = new Test();
      let result = await test.hello();
      done();
    } catch (e) {
      done(e);
    }
  });
}

沒 this: 使用 async + fat arrow 並且定義函式參數

export default class Test {
  hello = async (config) => {
    console.log(this); // 這裡沒東西
    let hello = 'yes!';
    return {hello};
  }
}
describe("Test this", () => {
  it.only("test", async done => {
    try {
      let test = new Test({});
      let result = await test.hello();
      done();
    } catch (e) {
      done(e);
    }
  });
}

有 this: 使用 fat arrow 不用 async

export default class Test {
  hello = (config) => {
    console.log(this); // 這裡有東西
    let hello = 'yes!';
    return {hello};
  }
}
describe("Test this", () => {
  it.only("test", done => {
    try {
      let test = new Test();
      let result = test.hello({});
      done();
    } catch (e) {
      done(e);
    }
  });
}

有 this: 使用 async 並且使用 class 的方式宣告(不用 fat arrow)

export default class Test {
  async hello (config) {
    console.log(this); // 這裡有東西
    let hello = 'yes!';
    return {hello};
  }
}
describe("Test this", () => {
  it.only("test", async done => {
    try {
      let test = new Test();
      let result = await test.hello({});
      done();
    } catch (e) {
      done(e);
    }
  });
}

目前還沒有辦法知道詳細原因,先做筆記,只知道使用 fat arrow + async + 參數會造成 this undefined,怪哉!

結論

上述就是目前有遇到的差異以及需要注意的地方,給大家參考,一旦升級之後,統一都使用 async/await,在也不會搞混了。

若有其他新的發現會再陸續補上,若有沒有注意到的也請不吝告知 🙂

參考

http://n.thepana.com/2015/11/25/koa2-0/

https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0#.k4730osf2

http://stackoverflow.com/questions/33505992/babel-6-changes-how-it-exports-default

http://www.2ality.com/2015/12/webpack-tree-shaking.html

產品資訊
tilda.lu

產品資訊

Ut Elit Tellus, Luctus Nec Ullamcorper Mattis, Pulvinar Dapibus Leo. Donec Sodales Sagittis Magna. Sed Consequat, Leo Eget Bibendum Sodales, Augue Velit Cursus Nunc, Quis Gravida Magna Mi A Libero. Lorem Ipsum Dolor Sit Amet, Consectetur Adipiscing.Ut Elit Tellus, Luctus Nec Ullamcorper Mattis, Pulvinar Dapibus Leo. Donec Sodales Sagittis Magna. Sed Consequat, Leo Eget Bibendum Sodales, Augue Velit Cursus Nunc, Quis Gravida Magna Mi A Libero. Lorem Ipsum Dolor Sit Amet, Consectetur Adipiscing.

閱讀更多 »

Do You Want To Boost Your Business?​

Drop Us A Line And Keep In Touch​