有哪些常見的Loader劲弦?你用過哪些Loader?
-
raw-loader
:加載文件原始內(nèi)容(utf-8) -
file-loader
:把文件輸出到一個(gè)文件夾中华畏,在代碼中通過相對(duì) URL 去引用輸出的文件 (處理圖片和字體) -
url-loader
:與file-loader
類似,區(qū)別是用戶可以設(shè)置一個(gè)閾值,大于閾值時(shí)返回其 publicPath歧譬,小于閾值時(shí)返回文件 base64 形式編碼 (處理圖片和字體) -
svg-inline-loader
:將壓縮后的 SVG 內(nèi)容注入代碼中 -
image-loader
:加載并且壓縮圖片文件 -
json-loader
:加載 JSON 文件(默認(rèn)包含) -
handlebars-loader
: 將 Handlebars 模版編譯成函數(shù)并返回 -
style-loader
:把 CSS 代碼注入到 JavaScript 中,通過 DOM 操作去加載 CSS -
postcss-loader
:擴(kuò)展 CSS 語法搏存,使用下一代 CSS瑰步,可以配合 autoprefixer 插件自動(dòng)補(bǔ)齊 CSS3 前綴 -
sass-loader
:將SCSS/SASS代碼轉(zhuǎn)換成CSS -
css-loader
:加載 CSS,支持模塊化璧眠、壓縮缩焦、文件導(dǎo)入等特性 -
source-map-loader
:加載額外的 Source Map 文件读虏,以方便斷點(diǎn)調(diào)試 -
babel-loader
:把 ES6 轉(zhuǎn)換成 ES5 -
ts-loader
: 將 TypeScript 轉(zhuǎn)換成 JavaScript -
awesome-typescript-loader
:將 TypeScript 轉(zhuǎn)換成 JavaScript,性能優(yōu)于 ts-loader -
eslint-loader
:通過 ESLint 檢查 JavaScript 代碼 -
tslint-loader
:通過 TSLint檢查 TypeScript 代碼 -
vue-loader
:加載 Vue.js 單文件組件 -
mocha-loader
:加載 Mocha 測試用例的代碼 -
coverjs-loader
:計(jì)算測試的覆蓋率 -
i18n-loader
: 國際化 -
cache-loader
: 可以在一些性能開銷較大的 Loader 之前添加袁滥,目的是將結(jié)果緩存到磁盤里
更多 Loader
請(qǐng)參考官網(wǎng)
有哪些常見的Plugin盖桥?你用過哪些Plugin?(加粗部分為webpack提速相關(guān)插件)
-
define-plugin
:定義環(huán)境變量 (Webpack4 之后指定 mode 會(huì)自動(dòng)配置) -
ignore-plugin
:忽略部分文件 -
html-webpack-plugin
:簡化 HTML 文件創(chuàng)建 (依賴于 html-loader) -
web-webpack-plugin
:可方便地為單頁應(yīng)用輸出 HTML题翻,比 html-webpack-plugin 好用 -
mini-css-extract-plugin
: 分離樣式文件揩徊,CSS 提取為獨(dú)立文件,支持按需加載 (替代extract-text-webpack-plugin) -
serviceworker-webpack-plugin
:為網(wǎng)頁應(yīng)用增加離線緩存功能 -
clean-webpack-plugin
: 目錄清理 -
uglifyjs-webpack-plugin
:不支持 ES6 壓縮 (Webpack4 以前) -
terser-webpack-plugin
: 支持壓縮 ES6 (Webpack4) -
webpack-parallel-uglify-plugin
: 多進(jìn)程執(zhí)行代碼壓縮嵌赠,提升構(gòu)建速度 -
ModuleConcatenationPlugin
: 開啟 Scope Hoisting -
speed-measure-webpack-plugin
: 可以看到每個(gè) Loader 和 Plugin 執(zhí)行耗時(shí) (整個(gè)打包耗時(shí)塑荒、每個(gè) Plugin 和 Loader 耗時(shí)) -
webpack-bundle-analyzer
: 可視化 Webpack 輸出文件的體積 (業(yè)務(wù)組件、依賴第三方模塊)
更多 Plugin
請(qǐng)參考官網(wǎng)
Loader和Plugin的區(qū)別
Loader
本質(zhì)就是一個(gè)函數(shù)猾普,在該函數(shù)中對(duì)接收到的內(nèi)容進(jìn)行轉(zhuǎn)換袜炕,返回轉(zhuǎn)換后的結(jié)果。因?yàn)?Webpack 只認(rèn)識(shí) JavaScript初家,所以 Loader 就成了翻譯官偎窘,對(duì)其他類型的資源進(jìn)行轉(zhuǎn)譯的預(yù)處理工作。
Plugin
就是插件溜在,基于事件流框架 Tapable
陌知,插件可以擴(kuò)展 Webpack 的功能,在 Webpack 運(yùn)行的生命周期中會(huì)廣播出許多事件掖肋,Plugin 可以監(jiān)聽這些事件仆葡,在合適的時(shí)機(jī)通過 Webpack 提供的 API 改變輸出結(jié)果。
Loader
在 module.rules 中配置志笼,作為模塊的解析規(guī)則沿盅,類型為數(shù)組。每一項(xiàng)都是一個(gè) Object纫溃,內(nèi)部包含了 test(類型文件)腰涧、loader、options (參數(shù))等屬性紊浩。
Plugin
在 plugins 中單獨(dú)配置窖铡,類型為數(shù)組,每一項(xiàng)是一個(gè) Plugin 的實(shí)例坊谁,參數(shù)都通過構(gòu)造函數(shù)傳入费彼。
Webpack構(gòu)建流程
Webpack 的運(yùn)行流程是一個(gè)串行的過程,從啟動(dòng)到結(jié)束會(huì)依次執(zhí)行以下流程:
-
初始化參數(shù)
:從配置文件和 Shell 語句中讀取與合并參數(shù)口芍,得出最終的參數(shù) -
開始編譯
:用上一步得到的參數(shù)初始化 Compiler 對(duì)象箍铲,加載所有配置的插件,執(zhí)行對(duì)象的 run 方法開始執(zhí)行編譯 -
確定入口
:根據(jù)配置中的 entry 找出所有的入口文件 -
編譯模塊
:從入口文件出發(fā)鬓椭,調(diào)用所有配置的 Loader 對(duì)模塊進(jìn)行翻譯虹钮,再找出該模塊依賴的模塊聋庵,再遞歸本步驟直到所有入口依賴的文件都經(jīng)過了本步驟的處理 -
完成模塊編譯
:在經(jīng)過第4步使用 Loader 翻譯完所有模塊后,得到了每個(gè)模塊被翻譯后的最終內(nèi)容以及它們之間的依賴關(guān)系 -
輸出資源
:根據(jù)入口和模塊之間的依賴關(guān)系芙粱,組裝成一個(gè)個(gè)包含多個(gè)模塊的 Chunk,再把每個(gè) Chunk 轉(zhuǎn)換成一個(gè)單獨(dú)的文件加入到輸出列表氧映,這步是可以修改輸出內(nèi)容的最后機(jī)會(huì) -
輸出完成
:在確定好輸出內(nèi)容后春畔,根據(jù)配置確定輸出的路徑和文件名,把文件內(nèi)容寫入到文件系統(tǒng)
在以上過程中岛都,Webpack
會(huì)在特定的時(shí)間點(diǎn)廣播出特定的事件律姨,插件在監(jiān)聽到感興趣的事件后會(huì)執(zhí)行特定的邏輯,并且插件可以調(diào)用 Webpack 提供的 API 改變 Webpack 的運(yùn)行結(jié)果臼疫。
簡單說:
- 初始化:啟動(dòng)構(gòu)建择份,讀取與合并配置參數(shù),加載 Plugin烫堤,實(shí)例化 Compiler
- 編譯:從 Entry 出發(fā)荣赶,針對(duì)每個(gè) Module 串行調(diào)用對(duì)應(yīng)的 Loader 去翻譯文件的內(nèi)容,再找到該 Module 依賴的 Module鸽斟,遞歸地進(jìn)行編譯處理
- 輸出:將編譯后的 Module 組合成 Chunk拔创,將 Chunk 轉(zhuǎn)換成文件,輸出到文件系統(tǒng)中
使用webpack開發(fā)時(shí)富蓄,你用過哪些可以提高效率的插件剩燥?
-
webpack-dashboard
:可以更友好的展示相關(guān)打包信息。 -
webpack-merge
:提取公共配置立倍,減少重復(fù)配置代碼 -
speed-measure-webpack-plugin
:簡稱 SMP晒他,分析出 Webpack 打包過程中 Loader 和 Plugin 的耗時(shí),有助于找到構(gòu)建過程中的性能瓶頸罢缸。 -
size-plugin
:監(jiān)控資源體積變化分俯,盡早發(fā)現(xiàn)問題 -
HotModuleReplacementPlugin
:模塊熱替換
source map是什么?生產(chǎn)環(huán)境怎么用疆导?
source map
是將編譯赁项、打包、壓縮后的代碼映射回源代碼的過程澈段。打包壓縮后的代碼不具備良好的可讀性悠菜,想要調(diào)試源碼就需要 soucre map。
map文件只要不打開開發(fā)者工具败富,瀏覽器是不會(huì)加載的悔醋。
線上環(huán)境一般有三種處理方案:
-
hidden-source-map
:借助第三方錯(cuò)誤監(jiān)控平臺(tái) Sentry 使用 -
nosources-source-map
:只會(huì)顯示具體行數(shù)以及查看源代碼的錯(cuò)誤棧。安全性比 sourcemap 高 -
sourcemap
:通過 nginx 設(shè)置將 .map 文件只對(duì)白名單開放(公司內(nèi)網(wǎng))
注意:避免在生產(chǎn)中使用 inline-
和 eval-
兽叮,因?yàn)樗鼈儠?huì)增加 bundle 體積大小芬骄,并降低整體性能猾愿。
模塊打包原理
Webpack
把解析的所有模塊變成一個(gè)對(duì)象,然后通過入口模塊去加載我們的東西账阻,然后依次實(shí)現(xiàn)遞歸的依賴關(guān)系蒂秘,通過入口來運(yùn)行所有的文件。Webpack 實(shí)際上為每個(gè)模塊創(chuàng)造了一個(gè)可以導(dǎo)出和導(dǎo)入的環(huán)境淘太,本質(zhì)上并沒有修改代碼的執(zhí)行邏輯姻僧,代碼執(zhí)行順序與模塊加載順序也完全一致。
文件監(jiān)聽原理
在發(fā)現(xiàn)源碼發(fā)生變化時(shí)蒲牧,自動(dòng)重新構(gòu)建出新的輸出文件撇贺。
Webpack開啟監(jiān)聽模式,有兩種方式:
- 啟動(dòng)
webpack
命令時(shí)冰抢,帶上--watch
參數(shù) - 在配置
webpack.config.js
中設(shè)置watch:true
缺點(diǎn):每次需要手動(dòng)刷新瀏覽器
原理:輪詢判斷文件的最后編輯時(shí)間是否變化松嘶,如果某個(gè)文件發(fā)生了變化,并不會(huì)立刻告訴監(jiān)聽者挎扰,而是先緩存起來翠订,等 aggregateTimeout
后再執(zhí)行。
module.export = {
// 默認(rèn)false,也就是不開啟
watch: true,
// 只有開啟監(jiān)聽模式時(shí)鼓鲁,watchOptions才有意義
watchOptions: {
// 默認(rèn)為空蕴轨,不監(jiān)聽的文件或者文件夾,支持正則匹配
ignored: /node_modules/,
// 監(jiān)聽到變化發(fā)生后會(huì)等300ms再去執(zhí)行骇吭,默認(rèn)300ms
aggregateTimeout:300,
// 判斷文件是否發(fā)生變化是通過不停詢問系統(tǒng)指定文件有沒有變化實(shí)現(xiàn)的橙弱,默認(rèn)每秒問1000次
poll:1000
}
}
Webpack 熱更新原理
Webpack
的熱更新又稱熱替換(Hot Module Replacement
),縮寫為 HMR
燥狰。這個(gè)機(jī)制可以做到不用刷新瀏覽器而將新變更的模塊替換掉舊的模塊棘脐。
HMR的核心就是客戶端從服務(wù)端拉去更新后的文件,準(zhǔn)確的說是 chunk diff (chunk 需要更新的部分)龙致,實(shí)際上 Webpack-dev-server
(WDS) 與瀏覽器之間維護(hù)了一個(gè) Websocket(websocket 可建立本地服務(wù)和瀏覽器的雙向通信蛀缝。),本地文件發(fā)生變化時(shí)目代,會(huì)通知瀏覽器熱更新代碼屈梁。
具體地說就是,當(dāng)本地資源發(fā)生變化時(shí)榛了,WDS 會(huì)向?yàn)g覽器推送更新在讶,并帶上構(gòu)建時(shí)的 hash,讓客戶端與上一次資源進(jìn)行對(duì)比霜大」共福客戶端對(duì)比出差異后會(huì)向 WDS 發(fā)起 Ajax
請(qǐng)求來獲取更改內(nèi)容(文件列表、hash)战坤,這樣客戶端就可以再借助這些信息繼續(xù)向 WDS 發(fā)起 jsonp
請(qǐng)求獲取該chunk的增量更新曙强。
后續(xù)的部分(拿到增量更新之后如何處理残拐?哪些狀態(tài)該保留?哪些又需要更新碟嘴?)由 HotModulePlugin
來完成溪食,提供了相關(guān) API 以供開發(fā)者針對(duì)自身場景進(jìn)行處理,像react-hot-loader
和 vue-loader
都是借助這些 API 實(shí)現(xiàn) HMR娜扇。具體可在這里了解
文件指紋是什么眠菇?怎么用?
文件指紋是打包后輸出的文件名的后綴袱衷。
-
Hash
:和整個(gè)項(xiàng)目的構(gòu)建相關(guān),只要項(xiàng)目文件有修改笑窜,整個(gè)項(xiàng)目構(gòu)建的 hash 值就會(huì)更改 -
Chunkhash
:和 Webpack 打包的 chunk 有關(guān)致燥,不同的 entry 會(huì)生出不同的 chunkhash -
Contenthash
:根據(jù)文件內(nèi)容來定義 hash,文件內(nèi)容不變排截,則 contenthash 不變
JS的文件指紋設(shè)置
設(shè)置 output 的 filename嫌蚤,用 chunkhash。
module.exports = {
entry: {
app: './scr/app.js',
search: './src/search.js'
},
output: {
filename: '[name][chunkhash:8].js',
path:__dirname + '/dist'
}
}
CSS的文件指紋設(shè)置
設(shè)置 MiniCssExtractPlugin 的 filename断傲,使用 contenthash脱吱。
module.exports = {
entry: {
app: './scr/app.js',
search: './src/search.js'
},
output: {
filename: '[name][chunkhash:8].js',
path:__dirname + '/dist'
},
plugins:[
new MiniCssExtractPlugin({
filename: `[name][contenthash:8].css`
})
]
}
圖片的文件指紋設(shè)置
設(shè)置file-loader的name,使用hash认罩。
占位符名稱及含義
- ext 資源后綴名
- name 文件名稱
- path 文件的相對(duì)路徑
- folder 文件所在的文件夾
- contenthash 文件的內(nèi)容hash箱蝠,默認(rèn)是md5生成
- hash 文件內(nèi)容的hash,默認(rèn)是md5生成
- emoji 一個(gè)隨機(jī)的指代文件內(nèi)容的emoj
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename:'bundle.js',
path:path.resolve(__dirname, 'dist')
},
module:{
rules:[{
test:/\.(png|svg|jpg|gif)$/,
use:[{
loader:'file-loader',
options:{
name:'img/[name][hash:8].[ext]'
}
}]
}]
}
}
在實(shí)際工程中垦垂,配置文件上百行乃是常事宦搬,如何保證各個(gè)loader按照預(yù)想方式工作?
可以使用 enforce
強(qiáng)制執(zhí)行 loader
的作用順序劫拗,pre
代表在所有正常 loader 之前執(zhí)行间校,post
是所有 loader 之后執(zhí)行。(inline 官方不推薦使用)
如何對(duì)bundle體積進(jìn)行監(jiān)控和分析页慷?
VSCode
中有一個(gè)插件 Import Cost
可以幫助我們對(duì)引入模塊的大小進(jìn)行實(shí)時(shí)監(jiān)測憔足,還可以使用 webpack-bundle-analyzer
生成 bundle
的模塊組成圖,顯示所占體積酒繁。
bundlesize
工具包可以進(jìn)行自動(dòng)化資源體積監(jiān)控滓彰。
如何優(yōu)化 Webpack 的構(gòu)建速度?
-
多進(jìn)程/多實(shí)例構(gòu)建
:HappyPack(不維護(hù)了)欲逃、thread-loader -
多進(jìn)程并行壓縮
- webpack-paralle-uglify-plugin(不再維護(hù))
- uglifyjs-webpack-plugin 開啟 parallel 參數(shù) (不支持ES6)
- terser-webpack-plugin 開啟 parallel 參數(shù)(支持ES6)
-
DLL
:- 使用 DllPlugin 進(jìn)行對(duì)第三方庫分包提前打包找蜜,使用 DllReferencePlugin(索引鏈接) 對(duì) manifest.json 引用,讓一些基本不會(huì)改動(dòng)的代碼先打包成靜態(tài)資源稳析,通過 json 文件告訴webpack這些庫提前打包好了洗做,避免反復(fù)編譯浪費(fèi)時(shí)間弓叛。
- HashedModuleIdsPlugin 可以解決模塊數(shù)字id問題
-
充分利用緩存提升二次構(gòu)建速度
:- babel-loader 開啟緩存
- terser-webpack-plugin 開啟緩存
- 使用 cache-loader 或者 hard-source-webpack-plugin
-
縮小構(gòu)建目標(biāo)/減少文件搜索范圍
:- exclude(不需要被解析的模塊)/include(需要被解析的模塊)
- resolve.modules 告訴 webpack 解析模塊時(shí)搜索的目錄,指明第三方模塊的絕對(duì)路徑
- resolve.mainFields 限定模塊入口文件名诚纸,只采用 main 字段作為入口文件描述字段 (減少搜索步驟撰筷,需要考慮到所有運(yùn)行時(shí)依賴的第三方模塊的入口文件描述字段)
- resolve.alias 當(dāng)從 npm 包中導(dǎo)入模塊時(shí)(例如,import * as React from 'react')畦徘,此選項(xiàng)將決定在 package.json 中使用哪個(gè)字段導(dǎo)入模塊毕籽。根據(jù) webpack 配置中指定的 target 不同,默認(rèn)值也會(huì)有所不同
- resolve.extensions 盡可能減少后綴嘗試的可能性
- noParse 對(duì)完全不需要解析的庫進(jìn)行忽略 (不去解析但仍會(huì)打包到 bundle 中井辆,注意被忽略掉的文件里不應(yīng)該包含 import关筒、require、define 等模塊化語句)
- IgnorePlugin (完全排除模塊)
-
動(dòng)態(tài)Polyfill
- 通過 Polyfill Service識(shí)別 User Agent杯缺,下發(fā)不同的 Polyfill蒸播,做到按需加載,社區(qū)維護(hù)萍肆。(部分國內(nèi)奇葩瀏覽器UA可能無法識(shí)別袍榆,但可以降級(jí)返回所需全部polyfill)
-
Scope hoisting (「作用域提升」)
- 構(gòu)建后的代碼會(huì)存在大量閉包,造成體積增大塘揣,運(yùn)行代碼時(shí)創(chuàng)建的函數(shù)作用域變多包雀,內(nèi)存開銷變大。Scope hoisting 把引入的 js 文件“提升到”它的引入者頂部亲铡,其實(shí)現(xiàn)原理為:分析出模塊之間的依賴關(guān)系才写,盡可能的把打散的模塊合并到一個(gè)函數(shù)中去,但前提是不能造成代碼冗余奴愉。因此只有那些被引用了一次的模塊才能被合并琅摩。
- 必須是ES6的語法,因?yàn)橛泻芏嗟谌綆烊圆捎?CommonJS 語法和 Scope Hoisting 要分析模塊之間的依賴關(guān)系锭硼,需要配置 mainFields 對(duì)第三方模塊優(yōu)先采用 jsnext:main 中指向的ES6模塊化語法
-
提取頁面公共資源
:- 使用 html-webpack-externals-plugin房资,將基礎(chǔ)包通過 CDN 引入,不打入 bundle 中
- 使用 SplitChunksPlugin 進(jìn)行(公共腳本檀头、基礎(chǔ)包轰异、頁面公共文件)分離(Webpack4內(nèi)置) ,替代了 CommonsChunkPlugin 插件
- 基礎(chǔ)包分離
-
Tree shaking
- purgecss-webpack-plugin 和 mini-css-extract-plugin配合使用(建議)
- 打包過程中檢測工程中沒有引用過的模塊并進(jìn)行標(biāo)記暑始,在資源壓縮時(shí)將它們從最終的bundle中去掉(只能對(duì)ES6 Modlue生效) 開發(fā)中盡可能使用ES6 Module的模塊搭独,提高tree shaking效率
- 禁用 babel-loader 的模塊依賴解析,否則 Webpack 接收到的就都是轉(zhuǎn)換過的 CommonJS 形式的模塊廊镜,無法進(jìn)行 tree-shaking
- 使用 PurifyCSS(不在維護(hù)) 或者 uncss 去除無用 CSS 代碼
更多優(yōu)化請(qǐng)參考官網(wǎng)-構(gòu)建性能
代碼分割的本質(zhì)是什么牙肝?有什么意義呢?
代碼分割的本質(zhì)其實(shí)就是在源代碼直接上線
和打包成唯一腳本main.bundle.js
這兩種極端方案之間的一種更適合實(shí)際場景的中間狀態(tài)。
「用可接受的服務(wù)器性能壓力增加來換取更好的用戶體驗(yàn)配椭〕媪铮」
- 源代碼直接上線:雖然過程可控,但是http請(qǐng)求多股缸,性能開銷大衡楞。
- 打包成唯一腳本:一把梭完自己爽,服務(wù)器壓力小敦姻,但是頁面空白期長瘾境,用戶體驗(yàn)不好。
是否寫過Loader镰惦?簡單描述一下編寫loader的思路迷守?
Loader 支持鏈?zhǔn)秸{(diào)用,所以開發(fā)上需要嚴(yán)格遵循“單一職責(zé)”旺入,每個(gè) Loader 只負(fù)責(zé)自己需要負(fù)責(zé)的事情盒犹。
Loader的API 可以去官網(wǎng)查閱
- Loader 運(yùn)行在 Node.js 中,我們可以調(diào)用任意 Node.js 自帶的 API 或者安裝第三方模塊進(jìn)行調(diào)用
- Webpack 傳給 Loader 的原內(nèi)容都是 UTF-8 格式編碼的字符串眨业,當(dāng)某些場景下 Loader 處理二進(jìn)制文件時(shí),需要通過 exports.raw = true 告訴 Webpack 該 Loader 是否需要二進(jìn)制數(shù)據(jù)
- 盡可能的異步化 Loader沮协,如果計(jì)算量很小龄捡,同步也可以
- Loader 是無狀態(tài)的,我們不應(yīng)該在 Loader 中保留狀態(tài)
- 使用 loader-utils 和 schema-utils 為我們提供的實(shí)用工具
- 加載本地 Loader 方法
- Npm link
- ResolveLoader
是否寫過Plugin慷暂?簡單描述一下編寫Plugin的思路聘殖?
webpack在運(yùn)行的生命周期中會(huì)廣播出許多事件,Plugin 可以監(jiān)聽這些事件行瑞,在特定的階段鉤入想要添加的自定義功能奸腺。Webpack 的 Tapable 事件流機(jī)制保證了插件的有序性,使得整個(gè)系統(tǒng)擴(kuò)展性良好血久。
Plugin的API 可以去官網(wǎng)查閱
- compiler 暴露了和 Webpack 整個(gè)生命周期相關(guān)的鉤子
- compilation 暴露了與模塊和依賴有關(guān)的粒度更小的事件鉤子
- 插件需要在其原型上綁定apply方法突照,才能訪問 compiler 實(shí)例
- 傳給每個(gè)插件的 compiler 和 compilation對(duì)象都是同一個(gè)引用,若在一個(gè)插件中修改了它們身上的屬性氧吐,會(huì)影響后面的插件
- 找出合適的事件點(diǎn)去完成想要的功能
- emit 事件發(fā)生時(shí)讹蘑,可以讀取到最終輸出的資源、代碼塊筑舅、模塊及其依賴座慰,并進(jìn)行修改(emit 事件是修改 Webpack 輸出資源的最后時(shí)機(jī))
- watch-run 當(dāng)依賴的文件發(fā)生變化時(shí)會(huì)觸發(fā)
- 異步的事件需要在插件處理完任務(wù)時(shí)調(diào)用回調(diào)函數(shù)通知 Webpack 進(jìn)入下一個(gè)流程,不然會(huì)卡住
聊一聊Babel原理吧
大多數(shù)JavaScript Parser遵循 estree
規(guī)范翠拣,Babel
最初基于 acorn
項(xiàng)目(輕量級(jí)現(xiàn)代 JavaScript 解析器)版仔,Babel 是對(duì)瀏覽器識(shí)別不了的代碼進(jìn)行轉(zhuǎn)換兼容的庫,Babel大概分為三大部分:
-
Parser
解析:將代碼轉(zhuǎn)換成抽象語法樹 (AbstractSyntaxTree,簡稱 AST)
- 詞法分析:將字符串形式的代碼分割為
令牌(token)
流蛮粮,即語法單元成的數(shù)組 - 語法分析:將token流轉(zhuǎn)換成 AST
- 詞法分析:將字符串形式的代碼分割為
-
Transformer
轉(zhuǎn)換:根據(jù)配置好的plugins/presets
把Parser
生成的 AST 轉(zhuǎn)變?yōu)樾碌?AST- Taro就是利用 babel 完成的小程序語法轉(zhuǎn)換
-
Generator
生成:把新的 AST 生成代碼
想了解如何一步一步實(shí)現(xiàn)一個(gè)編譯器的同學(xué)可以移步 Babel 官網(wǎng)曾經(jīng)推薦的開源項(xiàng)目the-super-tiny-compiler