網上關於babel7的文章很多,但是大多都沒有實踐,很多講的模稜兩可。 本文將手把手的帶你看各種配置下的輸入輸出轉換,徹底讓你瞭解babel7到底該怎麼去配置和優化。
首先我們知道進入了babel7的時代,stage-0這種已經作為不推薦使用的present了,最流行的應該是@babel/present-env 顧名思義讓babel擁有根據你的環境來編譯不同程式碼的需求。
targets
我們先配置最基礎的.babelrc配置
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"chrome": "58",
"ie": "10"
}
},
]
],
}
複製程式碼
targets配置的意思就是讓babel根據你寫入的相容平臺來做程式碼轉換,這裡我們指定ie10為我們要相容的最低版本,來看下面es6程式碼的輸出。
輸入: src/main.js
const a = () => {}
複製程式碼
輸出: dist/main.js
var a = function a() {};
複製程式碼
這裡因為ie10是不支援es6語法的,所以程式碼被全部轉換,如果我們把ie10這條去掉,因為高版本的chrome是支援es6大部分語法的,所以程式碼就不會被做任何轉換了。
browserlist 這裡是具體的可配置列表,可以根據你自己專案的相容性要求來配置。
useBuiltIns
首先我們來看一行簡單的程式碼
a.includes(1);
複製程式碼
includes作為陣列的例項方法,在某些瀏覽器其實是不支援的,babel預設的轉換對於這種場景並不會做處理,同樣不會處理的包括WeakMap, WeakSet, Promise等es6新引入的類,所以我們需要babel-polyfill為我們這些例項方法等等打上補丁。
在很多專案中我們會看到專案的main.js入口頂部require了babel-polyfill包, 或者指定webpack的entry為陣列,第一項引入babel-polyfill包,這樣的確沒問題而且很保險,但是很多場景下我們可能只是使用了少量需要polyfill的api,這個時候全量引入這個包就顯得很不划算,babel給我們提供了很好的解決方案,那就是useBuiltIns 這個配置,下面來看例項。
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"targets": {
"chrome": "58",
"ie": "10"
}
},
]
],
}
複製程式碼
輸入: src/main.js
a.includes(1)
Promise.reject()
複製程式碼
輸出: dist/main.js
require("core-js/modules/es6.promise");
require("core-js/modules/es7.array.includes");
require("core-js/modules/es6.string.includes");
a.includes(1);
Promise.reject();
複製程式碼
babel幫我們做好了程式碼分析,在需要用到polyfill的地方再幫你引入這個單獨的補丁,這樣就實現了按需引入~
@babel/plugin-transform-runtime
這個外掛是幫我們把一些babel的輔助方法由直接寫入程式碼專為按需引入模組的方式引用, 我們先來看不使用這個外掛時候,我們對於es6 class的轉換。
輸入: src/main.js
class A {}
複製程式碼
輸出: dist/main.js
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var A = function A() {
_classCallCheck(this, A);
};
複製程式碼
看似沒問題,轉換的很好,但是如果在很多模組都用了class語法的情況下呢?輔助函式_classCallCheck就會被重複寫入多次,佔用無意義的空間。 解決方法就是引入@babel/plugin-transform-runtime .babelrc
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"targets": {
"chrome": "58",
"ie": "10"
}
},
]
],
"plugins": [
"@babel/plugin-transform-runtime",
]
}
複製程式碼
輸入: src/main.js
class A {}
複製程式碼
輸出: dist/main.js
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var A = function A() {
(0, _classCallCheck2.default)(this, A);
};
複製程式碼
這樣就解決了輔助函式重複寫入的問題了。
總結
babel7的版本下,利用present-env做按需轉換,利用useBuiltIn做babel-polyfill的按需引入,利用transform-runtime做babel輔助函式的按需引入。