引言:很多人在學(xué)習(xí)Babel的時候,不知道怎么入手,除了那些生硬的配置文件,還要掌握哪些知(mian)識(shi)點(ti)呢?今天筆者就總結(jié)了一些你需要了解的Babel相關(guān)的知識點。
注:本篇是根據(jù)最新babel 7版本寫的,里面用到的一些babel相關(guān)包都是babel 7的
1,babel是如何工作的
babel是一個轉(zhuǎn)譯器,這里我嚴(yán)格區(qū)分了轉(zhuǎn)譯器和編譯器,因為編譯器最終生成的是機器指令,已經(jīng)和最初的代碼完全不一樣了,而轉(zhuǎn)譯器只是將高級別的語言轉(zhuǎn)化為低級別的語言,能更好的兼容,所以我把它稱作轉(zhuǎn)譯器,僅僅做了轉(zhuǎn)化。
babel的工作流程,簡單來說,就是傳入code字符串,經(jīng)過一系列處理后,吐出code字符串,就像這樣:
>Code => do something => Code
傳統(tǒng)編譯過程?(分詞/詞法分析,解析/語法分析AST,生成機器指令)
想了解更多JavaScript編譯相關(guān),請戳這里:

其實babel也類似,三個過程:解析,變換,再建
1,解析:
將代碼字符串解析成AST(抽象語法樹),在這一步里,babel會順帶進行語法的正確性校驗;
(關(guān)于這一步里,實際上就是編譯器過程的第一二兩步,生成AST的過程,具體的可參考之前的js編譯原理那篇隨筆)
2,變換:
遍歷整個抽象語法樹,對AST進行變換操作;
3,再建:
再次遞歸遍歷整個新的AST,根據(jù)變換后的AST再生成代碼字符串;
而我們在配置文件中寫的 presets 和 plugins 就是在第二階段 變換 過程中使用的。
2,plugin是干嘛用的
plugin就是用在do something的時候,如果沒有plugin,code還是原字符串返回,不作處理
plugin會運行在preset之前
plugin是從前往后,而preset是從后往前執(zhí)行
3,presets是干嘛用的
preset是用來組合plugin的,無需我們手動安裝很多plugin,而是提供了一組插件的集合(單點和套餐的區(qū)別)
比如我們用react的時候,我們就要添加@babel/preset-react,用ts的時候,就要添加@babel/preset-typescript
4,presets一些常見的配置項的功能及作用
env: 通過配置得知當(dāng)前目標(biāo)環(huán)境的特點,然后只做必要的轉(zhuǎn)換,如果不寫配置項,默認env為latest,也等價于es2015 + es2016 + es2017三個相加
5,其它一些相關(guān)的包
@babel/core
這個包里提供了很多代碼轉(zhuǎn)化的API,可以直接用里面的API對某一段代碼進行轉(zhuǎn)化,但是大部分情況我們不會手動調(diào)用,可是這個包確實必須要用的,因為其它的包會用到它。
@babel/preset-env
它是多個preset的集合,并且不斷在更新,我們可以通過配置項來決定需要支持的平臺(瀏覽器或者node平臺,不同版本下),然后按需加載插件,如果不配置,默認情況下和babel-preset-latest等同,會加載從es2015開始的所有preset
@babel/register
每當(dāng)使用 require 命令加載 .js, .jsx, .es, .es6 的后綴名文件時,會先用babel進行轉(zhuǎn)碼。
使用時必須先加載 require('@babel/register'),這個通常我們會在做服務(wù)端編譯的時候,引入這個。
@babel/polyfill
添加圖片注釋,不超過 140 字(可選)
從7.4版本開始,不推薦使用了,下面講一下原因:
babel默認只轉(zhuǎn)換js語法,不轉(zhuǎn)換新的API,比如 Iterator, Generator, Set, Maps, Proxy, Reflect, Symbol, Promise 等全局對象,以及一些定義在全局對象上的方法,比如 Array.from, Object.assign ,如果想用這些方法,就必須使用 @babel/polyfill ,它內(nèi)部集成了 core-js, regenerator
使用時必須在所有代碼運行之前加 :
require('@babel/polyfill');
所以之前通常也是在服務(wù)端代碼中加入這個。
缺點:
打出來的包非常大,因為它是一個整體,會一次性將所有的方法都加到原型鏈上,沒用到的那些方法也會加上去,所以可以單獨使用 core-js 的某個類庫來解決
會污染全局變量,因為直接在原型上做修改
如何解決這些缺點?使用 @babel/plugin-transform-runtime 和 @babel/runtime
@babel/plugin-transform-runtime 和 @babel/runtime
簡單來說,它能有效的減少重復(fù)代碼,并且可以實現(xiàn)在需要進行轉(zhuǎn)換的時候才轉(zhuǎn)換,不會像 @babel/polyfill 那樣一次性全部處理
使用時必須將 @babel/runtime 添加到 dependencies 中
那這樣的話,誰還用 @babel/polyfill 呢,是否有場景是必須要用它,而 @babel/runtime 解決不了的呢?
有, 實例方法無法轉(zhuǎn)碼,如
'!!!'.repeat(3); 'hello'.includes('h');
但是那都是過去了!
@babel/runtime-corejs3 里提供了對實例方法的轉(zhuǎn)碼,所以不用使用babel-polyfill,使用的時候在@babel/plugin-transform-runtime里配置屬性 corejs: 3
以上就是我在學(xué)習(xí)babel過程中覺得有價值的部分了,可能面試會遇到的這些問題,如果后續(xù)還看到有用的內(nèi)容,會繼續(xù)更新。
感興趣的同學(xué)可以留言一起討論哈!
文字免費,但碼字不易,記得點贊!
感興趣可關(guān)注一波,謝謝!
浙公網(wǎng)安備 33010602011771號