參考了很多文章庸娱,只是為了搞清楚babel 7 之后容易搞混的概念铃拇。
介紹
本文主要解決如下幾個問題:
- babel 是什么泰偿?
- babel 的原理是什么通危?
- babel 7 常見的核心包有哪些?
- babel 7 的最佳配置實(shí)踐
一灌曙、babel 是什么菊碟?
babel 是一個 JavaScript 編譯器。
除了常用的 將新語法轉(zhuǎn)換為向后兼容的語法
外在刺,還支持如下功能:
- 支持語法擴(kuò)展(例如 JSX)
- 支持靜態(tài)類型檢查的流式語法
二逆害、babel 的原理是什么头镊?
babel 的 三個主要處理步驟分別是:解析(parse)
、轉(zhuǎn)換(transform)
魄幕、生成(generate)
相艇。
2.1 解析
解析步驟接收代碼并輸出抽象語法樹(AST)。
- 詞法分析
詞法分析階段把字符串形式的代碼轉(zhuǎn)換為令牌(tokens)
流纯陨。 - 語法分析
語法分析階段使用令牌中的信息把令牌流轉(zhuǎn)換成 AST 的形式坛芽。
2.2 轉(zhuǎn)換
轉(zhuǎn)換步驟接收 AST 并對其進(jìn)行遍歷,在此過程中對節(jié)點(diǎn)進(jìn)行添加翼抠、更新及移除等操作咙轩。
2.3 生成
代碼生成步驟把最終的 AST 轉(zhuǎn)換成字符串形式的代碼,同時還會創(chuàng)建源碼映射阴颖。
三活喊、babel 7 常見的核心包有哪些?
3.1 @babel/preset-env
@babel/preset-env
是一個智能的 babel 預(yù)設(shè)量愧,讓你能使用最新的 JavaScript 語法钾菊,他會幫你轉(zhuǎn)換成代碼的目標(biāo)運(yùn)行環(huán)境支持的語法,提升你的開發(fā)效率并讓打包后的代碼體積更小偎肃。
運(yùn)行機(jī)制:
@babel/preset-env
依賴了許多優(yōu)秀的開源庫煞烫,并利用它們維護(hù)和增強(qiáng) Babel 語法轉(zhuǎn)換、語法實(shí)現(xiàn)软棺,來支持對于的目標(biāo)環(huán)境的版本的語法红竭、特征。
重要的配置項(xiàng):
target
可以指定瀏覽器類型喘落。
這里推薦使用單獨(dú)的文件 browserslistrc
來指定目標(biāo)瀏覽器茵宪,因?yàn)槌?babel 還有其他插件,例如 postcss 也會用到瘦棋。
useBuiltIns
配置@babel/preset-env
如何處理 polyfill
- entry
這個屬性將會把import "@babel/polyfill
或者require("@babel/polyfill")
替換成對應(yīng)環(huán)境(基于配置的目標(biāo)環(huán)境)的 polyfill稀火。 - usage
按需加載需要的polyfill, 一個打包的 bundle 之后加載一次。 - false
不加載polyfill
3.2 @babel/polyfill
@babel/polyfill
模塊包括core-js
和一個自定義的 regenerator runtime
模塊用于模擬完整的 ES2015+ 環(huán)境赌朋。
- 新的內(nèi)置組件:Promise凰狞、WeakMap
- 靜態(tài)方法:Array.from、Object,assign()
- 實(shí)例方法:Array.prototype.includes
- 生成器函數(shù)
弊端:會污染全局
Babel 7.4 之后廢棄了 @babel/polyfill
, 不再推薦使用沛慢。需要分別引入
import "core-js/stable";
import "regenerator-runtime/runtime";
3.3 @babel/plugin-transform-runtime
@babel/plugin-transform-runtime
是一個可重新使用Babel注入的幫助程序代碼以節(jié)省代碼大小的插件赡若。
諸如“ foobar” .includes(“ foo”)之類的實(shí)例方法僅適用于core-js @ 3。
如果您需要填充它們团甲,則可以直接導(dǎo)入“ core-js”或使用@babel/preset-env的useBuiltIns選項(xiàng)逾冬。
為什么需要 @babel/plugin-transform-runtime
?
默認(rèn)情況下,輔助函數(shù)將被添加到需要它的每個文件中。有時不需要重復(fù)身腻,特別是當(dāng)您的應(yīng)用程序分布在多個文件中時产还。
所有輔助函數(shù)都將引用模塊
@babel/runtime
,以避免在編譯后的輸出中出現(xiàn)重復(fù)嘀趟。運(yùn)行時將被編譯到您的構(gòu)建中脐区。該插件的另一個目的是為您的代碼創(chuàng)建一個沙盒環(huán)境。如果直接導(dǎo)入core-js或@babel/polyfill及其提供的內(nèi)置程序(例如Promise她按,Set和Map)牛隅,則這些將污染全局范圍。雖然這對于應(yīng)用程序或命令行工具可能是可以的尤溜,但是如果您的代碼是要發(fā)布供他人使用的庫倔叼,或者您無法完全控制代碼運(yùn)行的環(huán)境,則將成為一個問題宫莱。
corejs option | Install command |
---|---|
false | npm install --save @babel/runtime |
2 | npm install --save @babel/runtime-corejs2 |
3 | npm install --save @babel/runtime-corejs3 |
四丈攒、區(qū)分開發(fā)依賴和生產(chǎn)依賴
Babel 7.4 版本
需要作為開發(fā)依賴的:
@babel/preset-env
、@babel/plugin-transform-runtime
授霸、@babel/polyfill
需要作為生產(chǎn)依賴的:
@babel/runtime
巡验、regenerator-runtime
、core-js
總結(jié)
@babel/preset-env
是為了解決按需加載 polyfill
@babel/polyfill
是為了提供語法之外的墊片(內(nèi)置組件碘耳、靜態(tài)方法显设、實(shí)例方法等)
@babel/plugin-transform-runtime
是為了解決全局污染和輔助函數(shù)的重復(fù)引入
五、實(shí)踐
5.1 babel 的疑惑解答
說明一:@babel/preset-env
默認(rèn)配置辛辨,并不能完整的轉(zhuǎn)換 es6捕捂、以及 es7、es8 等新提案斗搞,它只能夠轉(zhuǎn)換新語法指攒,但是對于Array.includes() 、Promise 等并不支持
說明二:@babel/polyfill
提供了語法之外的墊片(內(nèi)置組件僻焚、靜態(tài)方法允悦、實(shí)例方法等),@babel/polyfill
依賴于 core-js
和 regenerator-runtime
實(shí)現(xiàn)的墊片
說明三: babel 7.4
之后廢棄了 @babel/polyfill
虑啤。
說明四:core-js
是 JavaScript 的模塊化標(biāo)準(zhǔn)庫隙弛,提供了大部分 ES2015+ 的 polyfill 。現(xiàn)在推薦使用 core-js@3
狞山。
說明五:regenerator-runtime
facebook 出品的一個提供編譯 generator
全闷、async/await
的獨(dú)立運(yùn)行時。
總結(jié):babel 7.4
之后@babel/preset-env
需要和 core-js
萍启、regenerator-runtime
搭配使用总珠,才能提供完整的 ES2015+ 環(huán)境
5.2 普通應(yīng)用的 babel 配置
安裝babel 相關(guān)的依賴
yarn add @babel/core @babel/preset-env babel-loader --dev
yarn add core-js@3
yarn add regenerator-runtime
webpack.config.js
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
.babelrc
文件
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3
}
]
]
}
說明一:babel-loader 是 webpack 的插件, 會默認(rèn)讀取 .babelrc
中的配置
說明二:core-js@3
和 regenerator-runtime
需要作為 dependencies
, 因?yàn)檫@兩個依賴中的部分或全部代碼會被引入進(jìn)代碼,作為 polyfill,屬于生產(chǎn)依賴姚淆。
說明三:useBuiltIns
的參數(shù)選擇,推薦選擇 usage
屡律,此選項(xiàng)將按需導(dǎo)入 polyfill腌逢。而 entry
會把全部的 polyfill 都引入到打包后的文件中。
說明四:useBuiltIns
會把 polyfill 引入到全局超埋,所以會污染全局搏讶。
說明五: useBuiltIns: usage
配置時,需要在主文件中主動引入 core-js
import "core-js/stable";
import "regenerator-runtime/runtime";
5.3 第三方庫的 babel 配置(待更新)
@babel/transform-runtime
會從 core-js-pure
這個包里去加載對應(yīng)的polyfill代碼霍殴,core-js-pure里面的代碼不會污染全局變量媒惕,適合第三方庫的開發(fā)。
-- 2020/01/07 更新 --
參考
babel 中文文檔-使用說明
Babel 手冊
劉小夕:不容錯過的 Babel7 知識
知乎:babel 只編譯語法
知乎:致我們學(xué)前端的小時光—corejs與env来庭、runtime的不解之緣
知乎:Babel學(xué)習(xí)系列4-polyfill和runtime差別(必看)
怎么給新手科普Babel:polyfill/preset-env/plugin-transform-runtime
關(guān)于Babel你只需要知道三個插件
一口(很長的)氣了解 babel
荒山:深入淺出 Babel 上篇:架構(gòu)和原理 + 實(shí)戰(zhàn)
倪曉磊:【工程化】@babel/preset-env 與@babel/plugin-transform-runtime 使用及場景區(qū)別