Babel:plugin、preset的區別與使用

文章概覽

本文主要內容包括:什麼是Babel Plugin、Babel Preset,二者的區別與聯繫、如何使用plugin/preset、如何建立自定義preset、使用注意事項。javascript

本文全部例子可在 筆者github 上 找到。java

Babel Plugin簡介

Babel是代碼轉換器,好比將ES6轉成ES5,或者將JSX轉成JS等。藉助Babel,開發者能夠提早用上新的JS特性,這對生產力的提高大有幫助。react

實現Babel代碼轉換功能的核心,就是Babel插件(plugin)。git

原始代碼 --> [Babel Plugin] --> 轉換後的代碼github

Babel Plugin例子

源代碼以下,這裏用到了兩個ES6才支持的新特性:箭頭函數、for...of。在只支持ES5的瀏覽器裏,這兩段代碼會報錯。npm

所以,能夠藉助插件將代碼轉成ES5。json

// index.js
// 箭頭函數
[1,2,3].map(n => n + 1);

// 模板字面量
let nick = '程序猿小卡';
let desc = `hello ${nick}`;

安裝依賴:瀏覽器

npm install --save-dev babel-cli 
npm install --save-dev babel-plugin-transform-es2015-arrow-functions
npm install --save-dev babel-plugin-babel-plugin-transform-es2015-template-literals

執行轉換,經過--plugins聲明依賴的插件,多個插件之間採用,進行分隔。bash

`npm bin`/babel --plugins babel-plugin-transform-es2015-arrow-functions,babel-plugin-transform-es2015-template-literals index.js

轉換結果以下:babel

[1, 2, 3].map(function (n) {
  return n + 1;
});

let nick = '程序猿小卡';
let desc = 'hello ' + nick;

轉換命令中,插件名稱能夠省去babel-plugin前綴:

`npm bin`/babel --plugins transform-es2015-arrow-functions,transform-es2015-template-literals index.js

也能夠改爲配置文件 .babelrc,plugins字段中聲明的插件會按照順序執行。

{
  "plugins": [
    "transform-es2015-arrow-functions",
    "transform-es2015-template-literals"
  ]
}

再次執行轉換命令:

`npm bin`/babel

Babel Preset簡介

Babel插件通常儘量拆成小的力度,開發者能夠按需引進。好比對ES6轉ES5的功能,Babel官方拆成了20+個插件。

這樣的好處顯而易見,既提升了性能,也提升了擴展性。好比開發者想要體驗ES6的箭頭函數特性,那他只須要引入transform-es2015-arrow-functions插件就能夠,而不是加載ES6全家桶。

但不少時候,逐個插件引入的效率比較低下。好比在項目開發中,開發者想要將全部ES6的代碼轉成ES5,插件逐個引入的方式使人抓狂,不單費力,並且容易出錯。

這個時候,能夠採用Babel Preset。

能夠簡單的把Babel Preset視爲Babel Plugin的集合。好比babel-preset-es2015就包含了全部跟ES6轉換有關的插件。

下面經過例子說明。

Babel Preset例子

仍是原來的代碼,此次採用babel-preset-es2015進行轉換。

首先,安裝依賴:

npm install --save-dev babel-cli 
npm install --save-dev babel-preset-es2015

執行轉換,經過--presets聲明依賴的preset,多個preset之間用,作分隔。

`npm bin`/babel --presets babel-preset-es2015 index.js
`npm bin`/babel --presets es2015 index.js # 也能夠去掉 babel-preset 前綴

一樣能夠採用配置文件 .babelrc。

{
  "presets": [ "es2015" ]
}

轉換命令:

`npm bin`/babel

Plugin與Preset執行順序

能夠同時使用多個Plugin和Preset,此時,它們的執行順序很是重要。

  1. 先執行完全部Plugin,再執行Preset。
  2. 多個Plugin,按照聲明次序順序執行。
  3. 多個Preset,按照聲明次序逆序執行。

好比.babelrc配置以下,那麼執行的順序爲:

  1. Plugin:transform-react-jsx、transform-async-to-generator
  2. Preset:es201六、es2015
{
  "plugins": [ 
    "transform-react-jsx",
    "transform-async-to-generator"
  ],
  "presets": [ 
    "es2015",
    "es2016"    
  ]
}

下面經過簡單例子進行說明。

Plugin、Preset混用例子

例子:將 index.jsx 編譯成 index.js,而且採用 ES5規範。這裏包含兩個步驟:

  1. jsx 語法轉成 js 語法。
  2. 將 ES6規範 轉成 ES5規範。

源代碼以下:

// index.jsx
var profile = <div>
  <img src="avatar.png" className="profile" />
  <h3>{[user.firstName, user.lastName].join(' ')}</h3>
</div>;

var foo = () => "foo";

安裝依賴:

npm install --save-dev babel-cli 
npm install --save-dev babel-plugin-transform-react-jsx 
npm install --save-dev babel-preset-es2015

配置文件 .babelrc:

{
  "plugins": [ "transform-react-jsx" ],
  "presets": [ "es2015" ]
}

執行轉換:

`npm bin`/babel index.jsx

轉換結果以下:

"use strict";

var profile = React.createElement(
  "div",
  null,
  React.createElement("img", { src: "avatar.png", className: "profile" }),
  React.createElement(
    "h3",
    null,
    [user.firstName, user.lastName].join(' ')
  )
);

var foo = function foo() {
  return "foo";
};

讀者能夠試下下面命令,單獨採用bebel-preset-es2015進行代碼轉換,結果會報語法錯誤。這從側面能夠印證Plugin的執行順序在Preset以前。

`npm bin`/babel --presets es2015 index.jsx

自定義Babel Preset

前面提到,Preset是Plugin的集合。藉助強大的社區,常見的轉換功能都已經有人實現的,不少時候,開發者只須要按需引用便可。

在實際開發中,咱們須要用到的Plugin/Preset相對比較固定,若是每次都要重複編寫,或者拷貝babel配置文件,既繁瑣,又容易出錯。這個時候,能夠考慮自定義Babel Preset。

之前面的 index.jsjsx 編譯爲例,咱們用到了 babel-preset-es201五、babel-plugin-transform-react-jsx,能夠建立自定義的 preset,把它們包含進去:()

// mypreset.js
module.exports = {
  presets: [
    require("babel-preset-es2015"),
  ],
  plugins: [    
    require("babel-plugin-transform-react-jsx"),
  ]
};

而後,修改.babelrc。這裏由於是本地文件,全部用到了相對路徑,若是發佈到了npm上,就能夠直接用包名。

{
  "presets": [
    "./mypreset.js"
  ]
}

轉碼過程略,讀者自行嘗試。

Plugin/Preset配置項

Babel Plugin、Babel Preset都支持配置項,配置項語法都是相同的,以下所示(插件相似)。

{
    "presets": [ 
        presetName01, // 沒有配置
        [ presetName02, presetOptions02 ] // 有配置
    ]
}

具體例子以下:

{
  "presets": [
    ["es2015", {
      "loose": true,
      "modules": false
    }]
  ]
}

不一樣Plugin/Preset的配置項做用可能不一樣,具體請查閱它們的官方文檔。

相關連接

https://babeljs.io/docs/plugins/

2018.05.31-babel-plugin-preset

相關文章
相關標籤/搜索