如何寫好.babelrc?Babel的presets和plugins配置解析

發表於2017-04-18

什麼是Babel

The compiler for writing next generation JavaScript.

官網是這麼說的,翻譯一下就是下一代JavaScript 語法的編譯器。

作為前端開發,由於瀏覽器的版本和相容性問題,很多JavaScript的新的方法都不能使用,等到可以大膽使用的時候,可能已經過去了好幾年。Babel就因此而生,它可以讓你放心使用大部分的JavaScript的新的標準的方法,然後編譯成相容絕大多數的主流瀏覽器的程式碼。

在升級到了Babel6.x版本之後,所有的外掛都是可插拔的。這也意味著你安裝了Babel之後,是不能工作的,需要配置對應的.babelrc檔案才能發揮完整的作用。下面就對Babel的presets和plugins配置做一個簡單解析。

所有配置根據官方文件提供,更新時間:2016-12-05。

預設(presets)

使用的時候需要安裝對應的外掛,對應babel-preset-xxx,例如下面的配置,需要npm install babel-preset-es2015。

env

最近新增的一個選項,有以下options選擇。

targets: { [string]: number },預設{}

需要支援的環境,可選例如:chrome, edge, firefox, safari, ie, ios, node,甚至可以制定版本,如node: 6.5。也使用node: current代表使用當前的版本。

browsers: Array | string,預設[]

瀏覽器列表,使用的是browserslist,可選例如:last 2 versions, > 5%。

loose: boolean,預設false

是否使用寬鬆模式,如果設定為true,plugins裡的外掛如果允許,都會採用寬鬆模式。

debug: boolean,預設false

編譯是否會去掉console.log。

whitelist: Array,預設[]

設定一直引入的plugins列表。

es2015/es2016/es2017/latest

es2015

使用es2015的,也就是我們常說的es6的相關方法,簡單翻譯如下,更多細節可以參看文件

  • check-es2015-constants // 檢驗const常量是否被重新賦值
  • transform-es2015-arrow-functions // 編譯箭頭函式
  • transform-es2015-block-scoped-functions // 函式宣告在作用域內
  • transform-es2015-block-scoping // 編譯const和let
  • transform-es2015-classes // 編譯class
  • transform-es2015-computed-properties // 編譯計算物件屬性
  • transform-es2015-destructuring // 編譯解構賦值
  • transform-es2015-duplicate-keys // 編譯物件中重複的key,其實是轉換成計算物件屬性
  • transform-es2015-for-of // 編譯for…of
  • transform-es2015-function-name // 將function.name語義應用於所有的function
  • transform-es2015-literals // 編譯整數(8進位制/16進位制)和unicode
  • transform-es2015-modules-commonjs // 將modules編譯成commonjs
  • transform-es2015-object-super // 編譯super
  • transform-es2015-parameters // 編譯引數,包括預設引數,不定引數和解構引數
  • transform-es2015-shorthand-properties // 編譯屬性縮寫
  • transform-es2015-spread // 編譯展開運算子
  • transform-es2015-sticky-regex // 正則新增sticky屬性
  • transform-es2015-template-literals // 編譯模版字串
  • transform-es2015-typeof-symbol // 編譯Symbol型別
  • transform-es2015-unicode-regex // 正則新增unicode模式
  • transform-regenerator // 編譯generator函式

總結:常用的都覆蓋了,並不需要太關心內容,如果使用某些還不支援的語法導致報錯,可以回頭查一下支援的列表。

es2016

使用es2016的相關外掛,也就是es7,更多細節可以參看文件

  • transform-exponentiation-operator // 編譯冪運算子
es2017

使用es2017的相關外掛,也就是es8?,更多細節可以參看文件

  • syntax-trailing-function-commas // function最後一個引數允許使用逗號
  • transform-async-to-generator // 把async函式轉化成generator函式
latest

latest是一個特殊的presets,包括了es2015,es2016,es2017的外掛(目前為止,以後有es2018也會包括進去)。

react

react是一個比較特別的官方推薦的presets,大概是因為比較火吧。加入了flow,jsx等語法,具體可以看文件

stage-x(stage-0/1/2/3/4)

stage-x和上面的es2015等有些類似,但是它是按照JavaScript的提案階段區分的,一共有5個階段。而數字越小,階段越靠後,存在依賴關係。也就是說stage-0是包括stage-1的,以此類推。

stage-4

已完成的提案,與年度釋出的release有關,包含2015年到明年正式釋出的內容。例如,現在是2016年,stage-4應該是包括es2015,es2016,es2017。經過測試,babel-preset-stage-4這個npm包是不存在的,如果你單純的需要stage-4的相關方法,需要引入es2015~es2017的presets。

stage-3

除了stage-4的內容,還包括以下外掛,更多細節請看文件

  • transform-object-rest-spread // 編譯物件的解構賦值和不定引數
  • transform-async-generator-functions // 將async generator function和for await編譯為es2015的generator。
stage-2

除了stage-3的內容,還包括以下外掛,更多細節請看文件

  • transform-class-properties // 編譯靜態屬性(es2015)和屬性初始化語法宣告的屬性(es2016)。
stage-1

除了stage-2的內容,還包括以下外掛,更多細節請看文件

  • transform-class-constructor-call // 編譯class中的constructor,在Babel7中會被移除
  • transform-export-extensions // 編譯額外的exprt語法,如export * as ns from “mod”;細節可以看這個
stage-0

除了stage-1的內容,還包括以下外掛,更多細節請看文件

  • transform-do-expressions // 編譯do表示式
  • transform-function-bind // 編譯bind運算子,也就是::

外掛(plugins)

其實看了上面的應該也明白了,presets,也就是一堆plugins的預設,起到方便的作用。如果你不採用presets,完全可以單獨引入某個功能,比如以下的設定就會引入編譯箭頭函式的功能。

那麼,還有一些方法是presets中不提供的,這時候就需要單獨引入了,介紹幾個常見的外掛。

transform-runtime

主要有以下options選擇。

helpers: boolean,預設true

使用babel的helper函式。

polyfill: boolean,預設true

使用babel的polyfill,但是不能完全取代babel-polyfill。

regenerator: boolean,預設true

使用babel的regenerator。

moduleName: string,預設babel-runtime

使用對應module處理。

這裡的options一般不用自己設定,用預設的即可。這個外掛最大的作用主要有幾下幾點:

  • 解決編譯中產生的重複的工具函式,減小程式碼體積
  • 非例項方法的poly-fill,如Object.assign,但是例項方法不支援,如”foobar”.includes(“foo”),這時候需要單獨引入babel-polyfill

更多細節參見文件

transform-remove-console

使用這個外掛,編譯後的程式碼都會移除console.*,媽媽再也不用擔心線上程式碼有多餘的console.log了。當然很多時候,我們如果使用webpack,會在webpack中配置。

這也告訴我們,Babel不僅僅是編譯程式碼的工具,還能對程式碼進行壓縮,也許有一天,你不再需要程式碼壓縮的外掛了,因為你有了Babel!

自定義預設或外掛

Babel支援自定義的預設(presets)或外掛(plugins)。如果你的外掛在npm上,可以直接採用這種方式”plugins”: [“babel-plugin-myPlugin”],當然,你也可以縮寫,它和”plugins”: [“myPlugin”]是等價的。此外,你還可以採用本地的相對路徑引入外掛,比如”plugins”: [“./node_modules/asdf/plugin”]。

presets同理。

plugins/presets排序

也許你會問,或者你沒注意到,我幫你問了,plugins和presets編譯,也許會有相同的功能,或者有聯絡的功能,按照怎麼的順序進行編譯?答案是會按照一定的順序。

  • 具體而言,plugins優先於presets進行編譯。
  • plugins按照陣列的index增序(從陣列第一個到最後一個)進行編譯。
  • presets按照陣列的index倒序(從陣列最後一個到第一個)進行編譯。因為作者認為大部分會把presets寫成[“es2015”, “stage-0”]。具體細節可以看這個

總結

因為自己對.babelrc檔案的設定有點疑問,花了大半天擼了下官方的文件。很多內容是英文的,可能翻譯並不準確,希望大家多多指教。

這是我寫了半天發現比較推薦的配置(真的是太簡單了,還花了這麼久去看文件)。強烈推薦使用transform-runtime。

當然,如果你的專案需要react或者flow這些語法的編譯,請在presets里加入對應的值即可。如果你需要非例項方法”foobar”.includes(“foo”)之類的方法,按需引入babel-polyfill。

相關文章