如何用babel將ES6轉換為指定的版本的ES程式碼
由於新版本的ECMASscript的強大特性,使我們寫js程式碼更加得心應手,例如:calss,let,for…of,promise等等,但可惜的是這些js新特新只被最新版本的瀏覽器支援,那麼指定範圍的低版本的瀏覽器的支援就需要一個專門的工具,babel就是這樣的一塊前端工具。
但是babel系列的外掛現在越來越多,對於初次接觸使用它的人來說需要花費不少的時間,尤其是討厭英文的人。
babel-6已經放棄了原來的babel包,取而代之的是各種轉換外掛,剛開始,我也很納悶,為什麼要分這麼多外掛包呢,原先的一個不好嗎?隨著使用我麼發現,這些外掛的職責分明,避免了‘一刀切’的問題,不管你需不需要都給你編譯。
babel-loader
這個包是由babel團隊開發的loader,用來告訴webpack我想要對我的js程式碼進行相容性編譯。
babel-loader
只是起到一個通知者的角色,通知babel你需要幹活了,在webpack的module中使用程式碼如下:
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/, // 不對node_modules目錄下的檔案進行編譯,可以提升webpack打包速度,其他loader也有這個配置
use: {
loader: 'babel-loader' ,
// loader: 'babel-loader?cacheDirectory', // 使用快取目錄它可以進一步提升webpack的編譯速度
options: { // 這個配置項我們一般單獨拿出來,建立一個‘.babelrc’檔案來單獨存放配置項
presets: ['@babel/preset-env'],// babel預設
plugin: ['@babel/plugin-proposal-object-rest-spread'] // 所需要使用的外掛
}
}
}
]
}
babel-core
如果說 babel-loader
是告訴webpack我要對js檔案進行程式碼相容性編譯,那麼,webpack接下來就是要找babel,而bable的入口就是 babel-core
,只有通過它,webpack才能使用各種babel的api(前提是你安裝了相關的api)。
babel-preset-es* 和 babel-preset-stage-*
babel-preset-es2015
,babel-preset-es2016
,babel-preset-es2017
等等傻傻的分也分不清楚。
這些預設將支援ES6新語法的相容性編譯。
將程式碼轉化為 ES3
babel-preset-es3
將程式碼轉化為 ES5
'babel-preset-es2015' ,
'babel-preset-stage-0' ,
'babel-preset-stage-1' ,
'babel-preset-stage-2' ,
'babel-preset-stage-3' ,
將程式碼轉化為 ES6
'babel-preset-es2016' 將ES2016轉化成ES6,
'babel-preset-es2017' 將ES2017轉化成ES6,
預設只能將ES6語法編譯為你指定的ES版本語法,例如:箭頭函式,但是像 Array.from
這樣的API呢他無能為力。那麼,怎麼辦呢,我們下面來介紹幾種解決方案。
處理ES6 API
babel-polyfill
babel預設可以編譯幾乎所有的JavaScript新語法,但是對於API卻不能解決,解決這個問題babel用的是 babel-polyfill
(它有core-js和regenerator兩部分構成)。
執行安裝命令:
npm install --save-dev babel-polyfill
babel-polyfill
有三種引入方法。
1.那個模組需要就在那個模組引入,
require('babel-polyfill');
2.全域性引入方法1,在專案的入口檔案引入,如果專案有多個入口,則在每個需要的入口分別加入。
require('babel-polyfill');
3.全域性引入方法2,可以在專案的 webpack.config.js
的入口配置項中引入。
entry: {
app: ['babel-polyfill', './main.js']
},
這是第一種解決方案用來將ES6程式碼編譯為es5。但是這種方案,增加了一些不必要的程式碼,webpack打包後的檔案比較大,使用它還有一個問題就是容易造成全域性汙染。。
而剛剛好babel提供了babel-runtime。babel-plyfill我們以前經常用,而babel-runtime,則是現在常用的。
babel-runtime
babel-runtime不會汙染全域性物件。如:當前的執行環境如果不支援Symbol,可以訪問 babel-runtime/core-js/symbol
這裡重新定義了symbol,此外還有Promise,Set 和 Map 等。
babel-runtime
官方建議用在生產環境,而開發環境使用 babel-plugin-transform-runtime
babel-plugin-transform-runtime
引用自:https://github.com/babel/babel-loader
babel uses very small helpers for common functions such as _extend. By default this will be added to every file that requires it.
You can instead require the babel runtime as a separate module to avoid the duplication.
這段話的意思是說:
babel會使用一些非常小的輔助(helper)函式作為通用函式,例如:_extend
。預設情況下,這類函式將被新增到每個需要它的檔案中。這時你可以使用babel runtime作為單獨的模組來避免重複。
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/, // 不對node_modules目錄下的檔案進行編譯,可以提升webpack打包速度,其他loader也有這個配置
use: {
loader: 'babel-loader',
// loader: 'babel-loader?cacheDirectory', // 使用快取目錄它可以進一步提升webpack的編譯速度
options: { // 這個配置項我們一般單獨拿出來,建立一個‘.babelrc’檔案來單獨存放配置項
presets: ['@babel/preset-env'],// babel預設
plugin: ['@babel/transform-runtime']
}
}
}
]
}
babel-plugin-transform-runtime
包含一個內建的polyfill(它包含一個自定義的regenerator執行時和core.js),所以,在webpack中使用 ProvidePlugin
用 shimming
方法定義 Promise
將不起作用。
env preset
babel-preset-env
允許你指定一個程式碼執行環境,並且只編譯該環境缺少的特性。
而非 babel-pre-env
預設存在的問題在於它們往往做得太多。例如,大多數現代瀏覽器都支援ES6生成器。如果您使用 babel-preset-es2015
這些預設,ES6生成器函式將始終被轉換為複雜的ES5程式碼。
.babelrc
配置檔案如下:
"presets": [
[
"env",
{
"targets": {
"browsers": ["last 2 versions", "ie >= 7"]
}
}
]
]
支援最近兩個版本的瀏覽器和IE7以上的瀏覽器。
其它babel外掛
babel-plugin-tranform-classes
// 解決ES6類(class)的相容性
使用實踐
babel-core
,babel-preset-es2015
,babel-polyfill
,
首先,.babelrc
程式碼如下:
{
"presets": ["es2015"]
}
然後,修改 webpack.config.js
程式碼如下:
entry: {
app: ['babel-polyfill', './main.js']
},
babel-polyfill
還有其他的引入方式
babel-core
,babel-preset-es2015
,babel-transform-runtime
僅需要修改 .babelrc
程式碼如下:
{
"presets": ["es2015"],
"plugins": ["transform-runtime"]
}
babel-core
,babel-preset-es2015
,babel-transform-runtime
, babel-preset-stage-*
,
使用 babel-preset-stage-*
,我們就是想使用一些更新的js特性,以 babel-preset-stage-2
為例:
僅需要修改 .babelrc
程式碼如下:
{
"presets": ["es2015", "es-stage-2"],
"plugins": ["transform-runtime"]
}
babel-core
,babel-preset-es2015
,babel-transform-runtime
, babel-preset-env
給我們的專案指定支援的瀏覽器和執行環境。
僅需要修改 .babelrc
程式碼如下:
{
"presets": ["es2015"],
"plugins": ["transform-runtime"].
"env": {
"targets": {
"browsers": ["last 2 versions", "safari >= 7"], // 瀏覽器
"node": "6.10" // node
}
}
}
你可能發現這裡沒有介紹 babel-cli
, babel-register
和babel外掛,解釋一下,這裡主要是為了webpack的使用進行的介紹,如果有很多人需要的話可以在做介紹。
下一篇babel的文章我會介紹,如何在webpack中使用 babel-eslint
。
參考資料:
babel-preset-env: a preset that configures Babel for you
babel-preset-env from npmjs.com
babel中文參考手冊
其它關於webpack的系列文章webpack-learning