升級到Babel 7的經驗

Babel的最新版本Babel 7 已經在Henry Zhu的不斷努力下發布了,他真的是全身心地投入到了Babel的開發中,而Babel對於前端界的貢獻也是有目共睹,沒有這個神奇的編譯器,前端界要落地ES6語法恐怕還要再等十年。

最近我在給自己團隊的UI組件庫升級到Babel 7,沒有想象中那麼難,但也有一些需要注意的問題,這裏分享一些升級的體會和經驗。

關於stage-x插件的廢棄

Babel 7的改動還是不少的,一個比較大的改動在於移除了之前的stage-x插件,根據官方博客的解釋,stage-x插件原本是對應於ECMA Script提案中的不同階段,每個階段有不同特性,而stage-x插件事實上就是集合這個階段中幾種特性轉譯的插件,比如我們最經常看到的babel-preset-stage-0,其實就是這樣的:

module.exports = {
  presets: [
    require("babel-preset-stage-1")
  ],
  plugins: [
    require("babel-plugin-transform-do-expressions"),
    require("babel-plugin-transform-function-bind")
  ]
};

每個stage插件都會包含下一階段的所有插件,這就導致大家爲了能用上大多數特性,紛紛採用了babel-preset-stage-0,React項目中,我們最經常看到的babelrc配置是這樣的:

{
  "presets": ["es2015", "react", "stage-0"]
}

然而,提案一直在變,如今是stage 0的特性,可能之後就進入到了stage 1,也可能之後直接被否決拋棄掉,並不會進入到ES規範中。那麼babel是不是應該更新這些stage插件呢?如果更新了,現階段大量前端項目、npm庫都在使用這個stage插件,會不會突然發現就編譯不了某個特性了呢?

到底應該遵循規範,還是應該遷就老項目做兼容呢?

最後Babel團隊做出來的決定是,廢棄掉stage-x插件!這不僅僅是關乎上面這個問題,由於大家已經習慣了stage的配置,對於其中封裝的各個特性早已不再關心,廢除掉stage-x插件,開發者就得加上自己需要的插件,每個插件對應一個提案中的特性,這樣項目中的配置也能更清晰。

另外,之前的命名也由@babel/plugin-transform-改爲@babel/plugin-proposal-,就是爲了強調這只是一個提案中的特性,並不能確保它會出現在下一代的ES規範中。

es2015 插件 -> env 插件

babel-preset-env已經發布了一段時間,它相比es2015可以更加靈活地配置,Babel 7宣佈廢棄babel-preset-es201x而採用新的env插件也是理所當然,這個插件的配置不再贅述,可以參考官方文檔

說說babel-upgrade

爲了讓你更方便的升級到Babel 7,官方提供了一個工具babel-upgrade,對於已有的項目,只需要運行這樣一行命令就可以了:

npx babel-upgrade --write --install

但是這就是爲什麼我先寫了前面這兩節的原因,這個工具的本質其實就是把之前的es2015換成envstage-x換成各種proposal-xxx,並且加上了@babel作爲新的Babel 7生態統一使用的scope。如果之前的項目使用了stage-x插件,就會多出大量的插件,其實這裏面大部分插件都是無需使用的,你可以根據項目中用到的特性適當刪減。

事實上,我最後項目中只使用了一個插件,babelrc配置如下:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "modules": false
            }
        ],
        "@babel/preset-react"
    ],
    "plugins": ["@babel/proposal-class-properties"]
}

說說babel-plugin-transform-class-properties

這個插件在React項目中十分常用,因爲我們經常需要將React組件類中的方法的this綁定到組件本身,如果不用箭頭函數,我們就需要使用bind將函數一個個綁定好,但如果可以使用箭頭函數在class字段中直接綁定的話,就非常方便了,即:

class Bork {
    boundFunction = () => {
        return this.state;
    }
}

這樣,箭頭函數被當作成class的屬性來看待,this也不會指向undefined

這個特性就需要babel-plugin-transform-class-properties來轉譯,這個插件在原來是包含在stage-2裏面的,現在,就需要單獨引入。
當然其實這裏最好是引入@babel/plugin-proposal-class-properties,更加符合規範。

這個是屬於Class Field提案。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章