日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
探討Esbuild為什么那么快

[[404663]]

Esbuild 是什么

Esbuild 是一個(gè)非常新的模塊打包工具,它提供了與 Webpack、Rollup、Parcel 等工具「相似」的資源打包能力,卻有著高的離譜的性能優(yōu)勢(shì):

創(chuàng)新互聯(lián)建站長(zhǎng)期為成百上千客戶(hù)提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為柏鄉(xiāng)企業(yè)提供專(zhuān)業(yè)的做網(wǎng)站、成都做網(wǎng)站,柏鄉(xiāng)網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

從上到下,耗時(shí)逐步上升達(dá)到數(shù)百倍的差異,這個(gè)巨大的性能優(yōu)勢(shì)使得 Esbuild 在一眾基于 Node 的構(gòu)建工具中迅速躥紅,特別是 Vite 2.0 宣布使用 Esbuild 預(yù)構(gòu)建依賴(lài)后,前端社區(qū)關(guān)于它的討論熱度迅速上升。

那么問(wèn)題來(lái)了,這是怎么做到的?我翻閱了很多資料后,總結(jié)了一些關(guān)鍵因素:

下面展開(kāi)一一細(xì)講。

為什么快

語(yǔ)言?xún)?yōu)勢(shì)

大多數(shù)前端打包工具都是基于 JavaScript 實(shí)現(xiàn)的,而 Esbuild 則選擇使用 Go 語(yǔ)言編寫(xiě),兩種語(yǔ)言各自有其擅長(zhǎng)的場(chǎng)景,但是在資源打包這種 CPU 密集場(chǎng)景下,Go 更具性能優(yōu)勢(shì),差距有多大呢?比如計(jì)算 50 次斐波那契數(shù)列,JS 版本:

 
 
 
 
  1. function fibonacci(num) { 
  2.     if (num < 2) { 
  3.         return 1 
  4.     } 
  5.     return fibonacci(num - 1) + fibonacci(num - 2) 
  6.  
  7. (() => { 
  8.     let cursor = 0; 
  9.     while (cursor < 50) { 
  10.         fibonacci(cursor++) 
  11.     } 
  12. })() 

 

Go 版本:

 
 
 
 
  1. package main 
  2.  
  3. func fibonacci(num int) int{ 
  4.     if num<2{ 
  5.         return 1 
  6.     } 
  7.      
  8.     return fibonacci(num-1) + fibonacci(num-2) 
  9.  
  10. func main(){ 
  11.     for i := 0; i<50; i++{ 
  12.         fibonacci(i) 
  13.     } 

 

JavaScript 版本執(zhí)行耗時(shí)大約為 「332.58s」,Go 版本執(zhí)行耗時(shí)大約為 「147.08s」,兩者相差約 「1.25」 倍,這個(gè)簡(jiǎn)單實(shí)驗(yàn)并不能精確定量?jī)煞N語(yǔ)言的性能差別,但感官上還是能明顯感知 Go 語(yǔ)言在 CPU 密集場(chǎng)景下會(huì)有更好的性能表現(xiàn)。

歸根到底,雖然現(xiàn)代 JS 引擎與10年前相比有巨大的提升,但 JavaScript 本質(zhì)上依然是一門(mén)解釋型語(yǔ)言,JavaScript 程序每次執(zhí)行都需要先由解釋器一邊將源碼翻譯成機(jī)器語(yǔ)言,一邊調(diào)度執(zhí)行;而 Go 是一種編譯型語(yǔ)言,在編譯階段就已經(jīng)將源碼轉(zhuǎn)譯為機(jī)器碼,啟動(dòng)時(shí)只需要直接執(zhí)行這些機(jī)器碼即可。

這種語(yǔ)言層面的差異在打包場(chǎng)景下特別突出,說(shuō)的夸張一點(diǎn),JavaScript 運(yùn)行時(shí)還在解釋代碼的時(shí)候,Esbuild 已經(jīng)在解析用戶(hù)代碼;JavaScript 運(yùn)行時(shí)解釋完代碼剛準(zhǔn)備啟動(dòng)的時(shí)候,Esbuild 可能已經(jīng)打包完畢,退出進(jìn)程了!

所以在編譯運(yùn)行層面,Go 前置了源碼編譯過(guò)程,相對(duì) JavaScript 邊解釋邊運(yùn)行的方式有更高的執(zhí)行性能。

多線程優(yōu)勢(shì)

Go 天生具有多線程運(yùn)行能力,而 JavaScript 本質(zhì)上是一門(mén)單線程語(yǔ)言,直到引入 WebWorker 規(guī)范之后才有可能在瀏覽器、Node 中實(shí)現(xiàn)多線程操作。

我曾經(jīng)研讀過(guò) Rollup、Webpack 的代碼,就我熟知的范圍內(nèi)兩者均未使用 WebWorker 提供的多線程能力。反觀 Esbuild,它最核心的賣(mài)點(diǎn)就是性能,它的實(shí)現(xiàn)算法經(jīng)過(guò)非常精心的設(shè)計(jì),盡可能飽和地使用各個(gè) CPU 核,特別是打包過(guò)程的解析、代碼生成階段已經(jīng)實(shí)現(xiàn)完全并行處理。

除了 CPU 指令運(yùn)行層面的并行外,Go 語(yǔ)言多個(gè)線程之間還能共享相同的內(nèi)存空間,而 JavaScript 的每個(gè)線程都有自己獨(dú)有的內(nèi)存堆。這意味著 Go 中多個(gè)處理單元,例如解析資源 A 的線程,可以直接讀取資源 B 線程的運(yùn)行結(jié)果,而在 JavaScript 中相同的操作需要調(diào)用通訊接口 woker.postMessage 在線程間復(fù)制數(shù)據(jù)。

所以在運(yùn)行時(shí)層面,Go 擁有天然的多線程能力,更高效的內(nèi)存使用率,也就意味著更高的運(yùn)行性能。

節(jié)制

對(duì),沒(méi)錯(cuò),節(jié)制!

Esbuild 并不是另一個(gè) Webpack,它僅僅提供了構(gòu)建一個(gè)現(xiàn)代 Web 應(yīng)用所需的最小功能集合,未來(lái)也不會(huì)大規(guī)模加入我們業(yè)已熟悉的各類(lèi)構(gòu)建特性。最新版本 Esbuild 的主要功能特性有:

  • 支持 js、ts、jsx、css、json、文本、圖片等資源
  • 增量更新
  • Sourcemap
  • 開(kāi)發(fā)服務(wù)器支持
  • 代碼壓縮
  • Code split
  • Tree shaking
  • 插件支持

可以看到,這份列表中支持的資源類(lèi)型、工程化特性非常少,甚至并不足以支撐一個(gè)大型項(xiàng)目的開(kāi)發(fā)需求。在這之外,官網(wǎng)明確聲明未來(lái)沒(méi)有計(jì)劃支持如下特性:

  • Elm, Svelte, Vue, Angular 等代碼文件格式
  • Ts 類(lèi)型檢查
  • AST 相關(guān)操作 API
  • Hot Module Replace
  • Module Federation

而且,Esbuild 所設(shè)計(jì)的插件系統(tǒng)也無(wú)意覆蓋以上這些場(chǎng)景,這就意味著第三方開(kāi)發(fā)者無(wú)法通過(guò)「插件」這種無(wú)侵入的方式實(shí)現(xiàn)上述功能,emmm,可以預(yù)見(jiàn)未來(lái)可能會(huì)出現(xiàn)很多魔改版本。

Esbuild 只解決一部分問(wèn)題,所以它的架構(gòu)復(fù)雜度相對(duì)較小,相對(duì)地編碼復(fù)雜度也會(huì)小很多,相對(duì)于 Webpack、Rollup 等大一統(tǒng)的工具,也自然更容易把性能做到極致。節(jié)制的功能設(shè)計(jì)還能帶來(lái)另外一個(gè)好處:完全為性能定制的各種附加工具。

定制

回顧一下,在 Webpack、Rollup 這類(lèi)工具中,我們不得不使用很多額外的第三方插件來(lái)解決各種工程需求,比如:

  • 使用 babel 實(shí)現(xiàn) ES 版本轉(zhuǎn)譯
  • 使用 eslint 實(shí)現(xiàn)代碼檢查
  • 使用 TSC 實(shí)現(xiàn) ts 代碼轉(zhuǎn)譯與代碼檢查
  • 使用 less、stylus、sass 等 css 預(yù)處理工具

我們已經(jīng)完全習(xí)慣了這種方式,甚至覺(jué)得事情就應(yīng)該是這樣的,大多數(shù)人可能根本沒(méi)有意識(shí)到事情可以有另一種解決方案。Esbuild 起了個(gè)頭,選擇完全!完全重寫(xiě)整套編譯流程所需要用到的所有工具!這意味著它需要重寫(xiě) js、ts、jsx、json 等資源文件的加載、解析、鏈接、代碼生成邏輯。

開(kāi)發(fā)成本很高,而且可能被動(dòng)陷入封閉的風(fēng)險(xiǎn),但收益也是巨大的,它可以一路貫徹原則,以性能為最高優(yōu)先級(jí)定制編譯的各個(gè)階段,比如說(shuō):

  • 重寫(xiě) ts 轉(zhuǎn)譯工具,完全拋棄 ts 類(lèi)型檢查,只做代碼轉(zhuǎn)換
  • 大多數(shù)打包工具把詞法分析、語(yǔ)法分析、符號(hào)聲明等步驟拆解為多個(gè)高內(nèi)聚低耦合的處理單元,各個(gè)模塊職責(zé)分明,可讀性、可維護(hù)性較高。而 Esbuild 則堅(jiān)持性能第一原則,不惜采用反直覺(jué)的設(shè)計(jì)模式,將多個(gè)處理算法混合在一起降低編譯過(guò)程數(shù)據(jù)流轉(zhuǎn)所帶來(lái)的性能損耗
  • 一致的數(shù)據(jù)結(jié)構(gòu),以及衍生出的高效緩存策略,下一節(jié)細(xì)講

這種深度定制一方面降低了設(shè)計(jì)成本,能夠保持編譯鏈條的架構(gòu)一致性;一方面能夠貫徹性能第一的原則,確保每個(gè)環(huán)節(jié)以及環(huán)節(jié)之間交互性能的最優(yōu)。雖然伴隨著功能、可讀性、可維護(hù)性層面的的犧牲,但在編譯性能方面幾乎做到了極致。

結(jié)構(gòu)一致性

上一節(jié)我們講到 Esbuild 選擇重寫(xiě)包括 js、ts、jsx、css 等語(yǔ)言在內(nèi)的轉(zhuǎn)譯工具,所以它更能保證源代碼在編譯步驟之間的結(jié)構(gòu)一致性,比如在 Webpack 中使用 babel-loader 處理 JavaScript 代碼時(shí),可能需要經(jīng)過(guò)多次數(shù)據(jù)轉(zhuǎn)換:

  • Webpack 讀入源碼,此時(shí)為字符串形式
  • Babel 解析源碼,轉(zhuǎn)換為 AST 形式
  • Babel 將源碼 AST 轉(zhuǎn)換為低版本 AST
  • Babel 將低版本 AST generate 為低版本源碼,字符串形式
  • Webpack 解析低版本源碼
  • Webpack 將多個(gè)模塊打包成最終產(chǎn)物

源碼需要經(jīng)歷 string => AST => AST => string => AST => string ,在字符串與 AST 之間反復(fù)橫跳。

而 Esbuild 重寫(xiě)大多數(shù)轉(zhuǎn)譯工具之后,能夠在多個(gè)編譯階段共用相似的 AST 結(jié)構(gòu),盡可能減少字符串到 AST 的結(jié)構(gòu)轉(zhuǎn)換,提升內(nèi)存使用效率。

總結(jié)

單純從編譯性能的維度看,Esbuild 確實(shí)完勝世面上所有打包框架,差距甚至能在百倍之大:

但這是有代價(jià)的,刨除語(yǔ)言層面的天然優(yōu)勢(shì)外,在功能層面它直接放棄對(duì) less、stylus、sass、vue、angular 等資源的支持,放棄 MF、HMR、TS 類(lèi)型檢查等功能,正如作者所說(shuō):

This will involve saying "no" to requests for adding major features to esbuild itself. I don't think esbuild should become an all-in-one solution for all frontend needs!

在我看來(lái),Esbuild 當(dāng)下與未來(lái)都不能替代 Webpack,它不適合直接用于生產(chǎn)環(huán)境,而更適合作為一種偏底層的模塊打包工具,需要在它的基礎(chǔ)上二次封裝,擴(kuò)展出一套既兼顧性能又有完備工程化能力的工具鏈,例如 Snowpack, Vite, SvelteKit, Remix Run 等。

總的來(lái)說(shuō),Esbuild 提供了一種新的設(shè)計(jì)思路,值得學(xué)習(xí)了解,但對(duì)大多數(shù)業(yè)務(wù)場(chǎng)景還不適合直接投入生產(chǎn)使用。


當(dāng)前標(biāo)題:探討Esbuild為什么那么快
網(wǎng)址分享:http://www.dlmjj.cn/article/cdhdejd.html