面試官:說(shuō)一下 esbuild?
【開(kāi)篇】esbuild 概述
專欄中的代碼均在 http://github.com/sunny-117/esbuild-book
完整版在掘金專欄地址:https://juejin.cn/column/7285233095058718756
什么是esbuild?
esbuild
是一款基于 Go
語(yǔ)言開(kāi)發(fā)的 javascript
構(gòu)建打包工具,相比傳統(tǒng)的構(gòu)建工具,主打性能優(yōu)勢(shì)。同樣規(guī)模的項(xiàng)目,使用 Esbuild
可以將打包速度提升 10
- 100
倍,這對(duì)廣大一直飽受 Webpack
緩慢打包速度折磨的開(kāi)發(fā)人員來(lái)說(shuō),簡(jiǎn)直就是福音。
為什么能這么快?
- Golang 開(kāi)發(fā)
采用 Go 語(yǔ)言開(kāi)發(fā),傳統(tǒng)的JS開(kāi)發(fā)的構(gòu)建工具并不適合資源打包這種 CPU 密集場(chǎng)景下,Go更具性能優(yōu)勢(shì)。
- 多核并行
go具有多線程運(yùn)行能力,而JS本質(zhì)上就是一門單線程語(yǔ)言。由于go的多個(gè)線程是可以共享內(nèi)存的,所以可以將解析、編譯和生成的工作并行化。
- 從零開(kāi)始
從一開(kāi)始就考慮性能,不使用第三方依賴,從始至終是使用的是一致的數(shù)據(jù)結(jié)構(gòu),從而避免數(shù)據(jù)轉(zhuǎn)換無(wú)意義的消耗。
- 內(nèi)存的有效利用
在 JS 開(kāi)發(fā)的傳統(tǒng)打包工具當(dāng)中一般會(huì)頻繁地解析和傳遞抽象語(yǔ)法樹(shù)( AST )數(shù)據(jù),比如 字符串 -> TS -> JS -> 字符串,然后字符串 -> JS -> 舊的JS -> 字符串,然后字符串 -> JS -> minified JS -> 字符串
,這其中會(huì)涉及復(fù)雜的編譯工具鏈,比如 webpack -> babel -> terser
,每次接觸到新的工具鏈,都得重新解析 AST,導(dǎo)致大量的內(nèi)存占用。
esbuild 僅觸及整個(gè)JavaScript AST 3次:
- 進(jìn)行詞法分析,解析,作用域設(shè)置和聲明符號(hào)的過(guò)程
- 綁定符號(hào),最小化語(yǔ)法。比如:將 JSX / TS轉(zhuǎn)換為 JS。
- AST生成JS,source map生成。
當(dāng) AST 數(shù)據(jù)在CPU緩存中仍然處于活躍狀態(tài)時(shí),會(huì)最大化AST數(shù)據(jù)的重用。
為什么還沒(méi)有一統(tǒng)江山?
雖然esbuild有很多優(yōu)點(diǎn),但是缺點(diǎn)也非常的明顯,從esbuild的官方文檔upcoming roadmap中,就能看出下面的問(wèn)題:
- ESbuild 沒(méi)有提供 AST 的操作能力,打包產(chǎn)物無(wú)法降級(jí)到 ES5 及以下,不能兼容一些低版本瀏覽器
- Code splitting 還在計(jì)劃中
- 沒(méi)有TS的類型檢測(cè)
- 默認(rèn)不支持vue,angular等代碼文件格式
- ......
簡(jiǎn)單來(lái)說(shuō),現(xiàn)在希望直接將esbuild放入到生產(chǎn)環(huán)境中,還需要一些路走,并不足以支撐一個(gè)大型項(xiàng)目的開(kāi)發(fā)需求。有些內(nèi)容雖然我們可以通過(guò)插件去實(shí)現(xiàn),但是并不是開(kāi)箱即用的功能,對(duì)于項(xiàng)目開(kāi)發(fā)的新手來(lái)說(shuō),并不友好。變相增加了開(kāi)發(fā)成本
為什么要學(xué)習(xí)esbuild?
無(wú)論如何,esbuild
為我們所熟知,還是因?yàn)?a rel="nofollow noopener noreferrer" target="_blank">Vite,esbuild
是組成Vite
的兩架馬車之一。
為什么Vite要使用esbuild?
一個(gè)字...快
現(xiàn)在來(lái)說(shuō),Vite在下面幾個(gè)地方都依托于esbuild,而未來(lái)隨著esbuild的完善,應(yīng)該會(huì)做進(jìn)一步處理
- 依賴預(yù)構(gòu)建---作為 Bundle 工具
- 單文件編譯——作為 TS 和 JSX 編譯工具
- 代碼壓縮——作為壓縮工具
什么是no-bundle?
ESM
是JavaScript
提出的官方標(biāo)準(zhǔn)化模塊系統(tǒng),不同于之前的CJS
,AMD
,CMD
等等,ESM
提供了更原生以及更動(dòng)態(tài)的模塊加載方案,最重要的就是它是瀏覽器原生支持的,也就是說(shuō)我們可以直接在瀏覽器中去執(zhí)行import
,動(dòng)態(tài)引入我們需要的模塊,而不是把所有模塊打包在一起。
Vite 是一個(gè)提倡 no-bundle
的構(gòu)建工具,相比于傳統(tǒng)的 Webpack,能做到開(kāi)發(fā)時(shí)的模塊按需編譯,而不用先打包完再加載。
什么是依賴預(yù)構(gòu)建?
模塊代碼其實(shí)分為兩部分,一部分是源代碼,也就是業(yè)務(wù)代碼,另一部分是第三方依賴的代碼,即node_modules
中的代碼。所謂的no-bundle
只是對(duì)于源代碼而言,對(duì)于第三方依賴而言,我們基本不會(huì)去改變他,Vite 還是選擇 bundle(打包),這個(gè)部分,就依賴于esbuild
。
但是關(guān)鍵點(diǎn)是,為什么在開(kāi)發(fā)階段我們要對(duì)第三方依賴進(jìn)行預(yù)構(gòu)建? 如果不進(jìn)行預(yù)構(gòu)建會(huì)怎么樣?
首先 Vite 是基于瀏覽器原生 ES 模塊規(guī)范實(shí)現(xiàn)的 Dev Server,不論是應(yīng)用代碼,還是第三方依賴的代碼,理應(yīng)符合 ESM 規(guī)范才能夠正常運(yùn)行。但是,我們沒(méi)有辦法控制第三方的打包規(guī)范。還有相當(dāng)多的第三方庫(kù)仍然沒(méi)有 ES 版本的產(chǎn)物。
此外,ESM還有一個(gè)比較重要的問(wèn)題——請(qǐng)求瀑布流問(wèn)題。ESM的每個(gè)import
都會(huì)觸發(fā)一次新的文件請(qǐng)求,因此在依賴層級(jí)深
、涉及模塊數(shù)量多
的情況下,會(huì)觸發(fā)很多個(gè)網(wǎng)絡(luò)請(qǐng)求,巨大的請(qǐng)求量加上 Chrome 對(duì)同一個(gè)域名下只能同時(shí)支持 6個(gè) HTTP 并發(fā)請(qǐng)求的限制,導(dǎo)致頁(yè)面加載十分緩慢,與 Vite 主導(dǎo)性能優(yōu)勢(shì)的初衷背道而馳。
在進(jìn)行依賴的預(yù)構(gòu)建之后,這種第三方庫(kù)的代碼被打包成了一個(gè)文件,這樣請(qǐng)求的數(shù)量會(huì)驟然減少,頁(yè)面加載也快了許多
完整版在掘金專欄地址:https://juejin.cn/column/7285233095058718756
#你認(rèn)為工作的意義是什么##曬一曬我的offer##我的求職思考##我的實(shí)習(xí)求職記錄##2022屆畢業(yè)生現(xiàn)狀#