背景
在專案迭代過程中,因為有相容 IE 的需求,根據文件使用babel-polyfill
和babel-runtime
兩個外掛解決問題。但是對於二者之間的恩怨情仇,卻不甚瞭解,便打算細細探究一番。
關於 Babel
如果我們沒有配置一些規則,Babel 預設只轉換新的 JavaScript 句法(syntax),而不轉換新的 API,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全域性物件,以及一些定義在全域性物件上的方法(比如 Object.assign )都不會轉碼。
所以,當這樣的程式碼出現時:
const key = `babel`
const obj = {
[key]: `foo`,
}
複製程式碼
Babel 預設會編譯成下面的程式碼
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });
} else {
obj[key] = value;
}
return obj;
}
var key = `babel`;
var obj = _defineProperty({}, key, Object.assign({}, { key: `foo` }));
複製程式碼
我們可以看到程式碼中多了一個名為_defineProperty
的幫助函式,但是這個幫助函式僅僅在當前模組中生效,因此其他模組中如果用到了同樣的語法,編譯後就會出現大量的重複程式碼。
babel-polyfill
原理是當執行環境中並沒有實現的一些方法,babel-polyfill 會給其做相容。
但是這樣做也有一個缺點,就是會汙染全域性變數,而且專案打包以後體積會增大很多,因為把整個依賴包也搭了進去。所以並不推薦在一些方法類庫中去使用。
用法
1. `npm install --save babel-polyfill`
2. 在應用的入口引用,以確保它能夠最先載入:
`import "babel-polyfill";` 或者
`require("babel-polyfill");`
複製程式碼
babel-runtime
為了不汙染全域性物件和內建的物件原型,但是又想體驗使用新鮮語法的快感。就可以配合使用babel-runtime
和babel-plugin-transform-runtime
。
比如當前執行環境不支援promise
,可以通過引入babel-runtime/core-js/promise
來獲取promise
,
或者通過babel-plugin-transform-runtime
自動重寫你的promise
。也許有人會奇怪,為什麼會有兩個runtime
外掛,其實是有歷史原因的:剛開始開始只有babel-runtime
外掛,但是用起來很不方便,在程式碼中直接引入helper
函式,意味著不能共享,造成最終打包出來的檔案裡有很多重複的helper
程式碼。所以,Babel
又開發了babel-plugin-transform-runtime
,這個模組會將我們的程式碼重寫,如將Promise
重寫成_Promise
(只是打比方),然後引入_Promise helper
函式。這樣就避免了重複打包程式碼和手動引入模組的痛苦。
用法
1. `npm install --save-dev babel-plugin-transform-runtime`
2. `npm install --save babel-runtime`
3. 寫入 `.babelrc`
複製程式碼
{
"plugins": ["transform-runtime"]
}
複製程式碼
啟用外掛babel-plugin-transform-runtime
後,Babel
就會使用babel-runtime
下的工具函式,轉譯程式碼如下:
`use strict`;
var _defineProperty2 = require(`babel-runtime/helpers/defineProperty`);
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var key = `babel`;
var obj = (0, _defineProperty3.default)({}, key, `foo`);
複製程式碼
不足
babel-runtime
不能轉碼例項方法,比如這樣的程式碼:
`!!!`.repeat(3);
`hello`.includes(`h`);
複製程式碼
這隻能通過 babel-polyfill 來轉碼,因為 babel-polyfill 是直接在原型鏈上增加方法。
And more
隨著歷史程式的發展,新一代的 babel-prenset-env 很強大,瞭解一下?
參考連結
自由轉載-非商用-非衍生-保持署名(創意共享3.0許可證)