此篇來解決上篇提出的問題,官方給出babel-polyfill
和 babel-runtime
兩種解決方案來解決這種全局對象或全局對象方法不足的問題
1. babel-polyfill
babel-polyfill
會在應用中模擬一個 es2015+ 的環境,對新語法需要的新對象進行補全
使用 babel-polyfill
後,可以使用內置對象如 Promise
、WeakMap
,靜態方法如 Array.from
、Object.assign
,實例方法如 Array.prototypes.includes
以及 generator
函數
下載 babel-polyfill
npm i babel-polyfill --save
因爲這是一個
polyfill
(需要在你的源代碼之前運行),所以需要它是一個dependency
,而不是devDependency
1.1 幾種引入方式
引入方式很簡單,在入口文件引入 babel-polyfill
就好了
require('babel-polyfill')
或者es6的 import 'babel-polyfill'
如果是使用 webpack 可在 webpack.config.js
進行如下配置
module.exports = {
entry: ["babel-polyfill", "./app/js"],
};
1.2 babel-polyfill 的一些缺陷
babel-polyfill
可能會增加很多根本沒有用到的 polyfill;- 可能會污染子模塊的局部作用域,嚴重的可能會導致衝突
使用 babel-polyfill
前的包大小
使用 babel-polyfill
後的包大小
2. babel-runtime
接着是 babel-runtime
,簡單說 babel-runtime
更像是一種按需加載的實現,比如你哪裏需要使用 Promise
,只要在這個文件頭部 import Promise from 'babel-runtime/core-js/promise'
就行了
下載 babel-runtime
npm install --save babel-runtime
不過如果你許多文件都要使用 Promise
,難道每個文件都要 import
一遍不成?
當然不是,Babel 官方已考慮這種情況,只需要使用 babel-plugin-transform-runtime
就可以解決手動 import 的苦惱了
2.1 babel-plugin-transform-runtime
在下載 babel-runtime
的基礎上,下載 babel-plugin-transform-runtime
npm install --save-dev babel-plugin-transform-runtime
然後在 .babelrc
進行配置
{
"plugins": ["transform-runtime"]
}
2.1.1 技術細節
總的來說,babel-plugin-transform-runtime
就是可以在我們使用新 API 時自動 import babel-runtime
裏面的 polyfill,具體插件做了以下三件事情:
- 當我們使用 async/await 時,自動引入
babel-runtime/regenerator
- 當我們使用 ES6 的靜態事件或內置對象時,自動引入
babel-runtime/core-js
- 移除內聯babel helpers並替換使用
babel-runtime/helpers
來替換
使用 babel-plugin-transform-runtime
前包的大小
使用 babel-plugin-transform-runtime
後包的大小
2.2 babel-runtime 的優劣勢
此處說的優缺點是默認使用了
babel-plugin-transform-runtime
優勢
- 不會污染全局變量
- 多次使用只會打包一次
- 依賴統一按需引入,無重複引入,無多餘引入
- 避免 babel 編譯的工具函數在每個模塊裏重複出現,減小庫和工具包的體積
劣勢
- 不支持實例化的方法如
Array.includes(x)
就不能轉化 - 如果使用的API用的次數不是很多,那麼
transform-runtime
引入polyfill的包會比不是transform-runtime
時大
3. 總結
babel-polyfill
是在原有的JS內置對象及方法上做向後兼容的處理,比如說ES5裏面的 Object
是沒有自帶 assign
方法的,那麼你加載了babel-polyfill
之後,它就給 Object
擴展了一個 assign
方法,這樣你就可以直接使用 Object.assign(obj1, obj2)
了
而 babel-runtime
的方式則需要babel作爲工具,在轉換的過程中,檢測到你使用了 Object.assign
,而且你的 .babelrc
配置中需要對其做ES5兼容處理,那麼結合 babel-plugin-transform-runtime
,在該JS文件中引入 Object.assign
的Polyfill,這樣也能實現 Object.assign
的功能,但是你無法在 Object
上直接找到 assign
的方法