Babel:plugin、preset的區別與使用


文章概覽

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

本文所有例子可在 筆者github 上 找到。

Babel Plugin簡介

Babel是代碼轉換器,比如將ES6轉成ES5,或者將JSX轉成JS等。借助Babel,開發者可以提前用上新的JS特性,這對生產力的提升大有幫助。

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

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

Babel Plugin例子

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

因此,可以借助插件將代碼轉成ES5。

// 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聲明依賴的插件,多個插件之間采用,進行分隔。

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

轉換結果如下:

[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:es2016、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-es2015、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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM