以 async/await 爲例,說明 babel 插件怎麼搭

你必定碰到過這些庫

babel-polyfill

項目地址:https://github.com/babel/babe...node

經過兩個依賴實現功能git

  • core-js/shim 提供 ES5/6/7 標準方法的實現es6

  • regenerate-runtime 提供 async 語法編譯後的的運行時環境(下文會專門說明)github

babel-plugin-transform-runtime

項目地址:https://github.com/babel/babe...npm

開發 ES6/7 新特性的庫推薦使用該插件,須要注意的是,安裝時,必須同時安裝 babel-runtime 做爲依賴:babel

npm install --save-dev babel-plugin-transform-runtime
npm install --save babel-runtime // `babel-plugin-transform-runtime` 插件自己實際上是依賴於 `babel-runtime` 的,但爲了適應 `npm install --production` 強烈建議添加該依賴。

插件會將 es6/7 的語法轉化爲 es5 兼容的格式,並提供運行時依賴。什麼是運行時依賴?好比你要用 Array.from 方法,該方法的具體實現必須在代碼的執行環境中提供,這就是運行時依賴。app

該插件在轉化語法時,不會污染全局環境。而 babel-polyfill 則會污染全局環境。async

babel-plugin-external-helpers

項目地址:https://github.com/babel/babe...函數

代碼不多,只依賴於 babel-runtime。相比較 babel-plugin-transform-runtime 會在每一個模塊注入運行時代碼,該插件會將運行時代碼打包,相似封裝到一個對象下,這樣避免注入重複的代碼。工具

讓 async/await 跑起來

經過最簡單的一個函數:

async function foo() {
  return await 1
}

foo().then(function(val) {
  console.log(val)  // should output 1
})

說明這些 babel 插件怎麼搭配,三種方案:

方案一:regenerator

.babelrc 以下配置:

{
  "plugins": ["transform-runtime", "babel-plugin-transform-regenerator", "babel-plugin-transform-es2015-modules-commonjs"]
}
  • babel-plugin-transform-regenerator 將 async/await 語法轉化成 regenerator 庫支持的語法

  • transform-runtime 將運行時注入,相似:import regenerator from 'babel-runtime/regenerator'

  • babel-plugin-transform-es2015-modules-commonjs 只是爲了將 import 轉化爲 require,便於在 node.js 模塊下執行(若是你的執行環境支持 es6 的模塊機制,則不須要該插件)。

方案二:generator

這種方式,最適合 node.js 環境,node.js 最先從 0.11 開始,便支持 generator。.babelrc 以下配置:

{
  "plugins": ["babel-plugin-transform-async-to-generator"]
}

生成的代碼,在 node.js 環境下能夠直接執行,此時便再也不須要 babel 提供任何有關 generator 相關的運行時環境了,直接 node.js 自帶~

方案三:babel-polyfill

.babelrc 以下配置:

{
  "plugins": ["babel-plugin-transform-regenerator"]
}

其實和前面 regenerate 同樣,去掉了 runtime 配置。編譯結束後,須要手動在結果文件的第一行加入:

require('babel-polyfill')

經過 babel-polyfill 向全局注入運行時依賴。那何時該用 babel-polyfill 何時用 babel-runtime?官網給出瞭解釋:

This will emulate a full ES2015+ environment and is intended to be used in an application rather than a library/tool.

  • 若是是應用級別的開發,能夠考慮使用 babel-polyfill:大而全,支持全部的 es2015+ 特性。能夠在項目入口處統一添加,也能夠經過打包工具配置入口。

  • 若是是開發一個庫,使用 babel-runtime,不會污染全局,並且是根據狀況注入須要的運行時環境。

關於 babel-runtime 更多細節,強烈建議閱讀官方文檔:https://github.com/babel/babe...

別忘了 externel-helpers

剛剛只是一個簡單的 foo 函數,一個文件。多個文件時,存在每一個文件都注入相似 asyncToGenerator 等輔助方法,致使重複。舉例說明:

foo.js

'use strict'

const bar = require('./bar')

async function foo () {
  const val = await bar()
  console.log(val)
}

foo()

bar.js

'use strict'

module.exports = async function bar () {
  return await 'bar'
}

採用前文提到的 generator 方式,去編譯,會發現結果文件中,都有 _asyncToGenerator 定義。修改 .babelrc 以下:

{
  "plugins": ["babel-plugin-transform-async-to-generator", "babel-plugin-external-helpers"]
}

再編譯,_asyncToGenerator 都變成了 babelHelpers.asyncToGenerator。這樣,多個模塊之間沒有重複的代碼注入,更加乾淨清爽。不過此時 babelHelpers 是未定義,仍然須要引入運行時環境: transform-runtime,最終能夠運行的配置以下:

{
  "plugins": [
    "babel-plugin-transform-async-to-generator",
    "babel-plugin-external-helpers",
    "transform-runtime",
    "babel-plugin-transform-es2015-modules-commonjs"
  ]
}

示例代碼見 https://github.com/sabakugaar...

本文整理自:https://github.com/sabakugaar...

相關文章
相關標籤/搜索