你一定碰到過這些庫
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