剛開始使用babel的時候,很多童鞋只是單純跟着官網或則其他人的代碼去安裝一大堆bbabel相關的npm包,但是並不知道具體每個包都是什麼樣的作用,本文就是來闡述日常開發時用到的babel全家桶分別的作用、使用場景以及其原理。
什麼是babel
首先來看一下babel是什麼?
Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.
上面是官方文檔的描述,翻譯過來就是“babel是一個工具鏈,用來將es2015+的代碼轉化成在現有的或則更早的瀏覽器環境可以運行的向後兼容的JS語法”
// Babel Input: ES2015 arrow function
[1, 2, 3].map((n) => n + 1);
// Babel Output: ES5 equivalent
[1, 2, 3].map(function(n) {
return n + 1;
});
如何使用
babel的使用有很多種方式,本文主要來描述下日常開發經常使用到的兩種方式:命令行方式使用以及結合webpack來使用:
命令行方式使用
1. 安裝babel
```
npm i @babel/core @babel/cli -D
```
2. 在package.json中配置起使用方式
```
"scripts": {
"build": "babel src --out-dir ./",
},
```
這樣就可以將/src下的js文件編譯之後輸出到根目錄下了
webpack使用
結合webpack使用的時候就需要babel對應的loader,之後再webpack的配置文件下配置完成就可以
注: @babel/core是babel7版本的基礎包,是必須引入的。
```
npm i @babel/core babel-loader -D
module.exports = {
entry: './src/index.js',
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'bin')
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
},
exclude: /node_modules/,
}
]
}
};
```
配置
通過上述方式使用之後,就可以使用babel了,但是此時會發現編譯之後並沒有什麼變化,這是因爲我們需要增加配置信息來告訴babel要把代碼編譯成符合什麼標準的以及某些編譯還需要增加插件的應用,於是要解決以上兩個問題,我們就需要引入presets和plugins。
配置文件
.babelrc
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": ["> 0.25%", "not dead"]
}
}]
],
"plugins": ["@babel/transform-runtime"]
}
babel編譯過程中會讀取相應的配置文件來編譯源代碼
presets
預設其實就是一個預先設定的插件列表,使用一個預設就是將這個預設規定的全部插件安裝並使用,但是隨着插件的不斷增多,我們不可能會去記憶所有的語法功能對應的版本,於是出現了preset-env。
preset-env其實相當於是一個智能預設,會根據在配置文件中設置的目標瀏覽器來轉化成兼容的代碼。
```
npm i @babel/preset-env -D
.babelrc
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": ["> 0.25%", "not dead"]
}
}]
],
}
```
plugins
上述步驟之後基本上可以使用ES 2015+的一些特性了,但是會有一些如新的內置函數(Promise,Set,Map),靜態方法(Array.from,Object.assign),實例方法(Array.prototype.includes)等需要一些工具函數的處理,這時就需要用到plugins了,而babel的plugins分別有兩種:plugin-transform-runtime和babel-polyfill。
- plugin-transform-runtime
根據官方文檔的描述,babel在用工具函數來轉化語法的時候會產生很多的冗餘代碼,導致程序代碼冗餘,此時推出了plugin-transform-runtime,該插件的作用有兩個:
1. 將編譯時生成的工具函數映射到runtime上去,這樣可以避免工具函數的冗餘,因此@babel/runtime是一個運行時需要的插件;
2. 建立了一個沙盒環境,不會去污染全局變量,因此比較適合寫一些公用庫或則組件
```
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
```
編譯後如下:
```
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
```
可以看到直接引用的是runtime下的模塊,這樣的話就不會出現重複模塊了
- babel-polyfill
babel-polyfill一般用在命令行工具或則是開發app的時候,在入口處調用,之後會被放置到全局空間,根據目標瀏覽器去模擬一些工具函數的行爲。
```
npm install --save @babel/polyfill
import "@babel/polyfill";
```
但是由於babel-polyfill是模擬了整個ES 2015+的環境,因此並不被建議全部直接導入,而是配合presets下的useBuiltIns屬性一起來使用或則手動去導入需要的所有模塊。
```
.babelrc
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": ["> 0.25%", "not dead"]
},
"useBuiltIns": "usage"
}]
],
}
```
編譯之後的結果爲:
```
require("core-js/modules/es6.array.from");
require("core-js/modules/web.dom.iterable");
require("core-js/modules/es6.array.iterator");
require("core-js/modules/es6.object.to-string");
require("core-js/modules/es6.string.iterator");
require("core-js/modules/es6.map");
```
根據名字可以看出來是將用到的模塊都單個引入,減小了包體積
注:本項目採用babel 7,webpack 4