[轉] 以 async/await 為例,說明 babel 插件怎么搭


你一定碰到過這些庫

babel-polyfill

項目地址:https://github.com/babel/babel/blob/master/packages/babel-polyfill

通過兩個依賴實現功能

  • core-js/shim 提供 ES5/6/7 標准方法的實現
  • regenerate-runtime 提供 async 語法編譯后的的運行時環境(下文會專門說明)

babel-plugin-transform-runtime

項目地址:https://github.com/babel/babel/blob/master/packages/babel-plugin-transform-runtime

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

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 方法,該方法的具體實現必須在代碼的執行環境中提供,這就是運行時依賴。

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

babel-plugin-external-helpers

項目地址:https://github.com/babel/babel/blob/master/packages/babel-plugin-external-helpers/

代碼很少,只依賴於 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/babel/blob/master/packages/babel-plugin-transform-runtime/README.md

別忘了 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/sabakugaara/babel-example

本文整理自:https://github.com/sabakugaara/sabakugaara.github.io/issues/8


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM