深入剖析vite到底是快還是慢原理詳解
前言
談到 Vite
,給人的第一印象就是 dev server
啟動(dòng)速度快。同樣規(guī)模的項(xiàng)目,相比 Webpack
動(dòng)輒十幾秒甚至幾十秒的的啟動(dòng)速度,Vite
簡(jiǎn)直是快到?jīng)]朋友,往往數(shù)秒之內(nèi)即可完成啟動(dòng)(PS: 都沒(méi)有時(shí)間去喝一杯 ?? 啦)。
正好小編最近在做一些關(guān)于開發(fā)體驗(yàn)的性能優(yōu)化,就想著把手上一些項(xiàng)目的開發(fā)模式更新為 Vite
。經(jīng)過(guò)一番操作,終于改造成功,而效果也不負(fù)眾望,項(xiàng)目啟動(dòng)速度由原來(lái)的 25 s 如坐 ??一般躍升為 2 s,簡(jiǎn)直夸張。雖然也出現(xiàn)了一些諸如首屏、懶加載性能下降等負(fù)面效果,但整體來(lái)說(shuō)依然利大于弊,開發(fā)幸福感提升非常明顯。
接下來(lái)小編就通過(guò)本文給大家分析一下,具體聊一聊 Vite
的快和慢。
Vite 的快
Vite
的快,主要體現(xiàn)在兩個(gè)方面: 快速的冷啟動(dòng)和快速的熱更新。而 Vite
之所以能有如此優(yōu)秀的表現(xiàn),完全歸功于 Vite
借助了瀏覽器對(duì) ESM
規(guī)范的支持,采取了與 Webpack
完全不同的 unbundle
機(jī)制。
在本章節(jié),小編將通過(guò)一個(gè)實(shí)際的項(xiàng)目,分別使用 Webpack
和 Vite
啟動(dòng) dev server
, 給大家展示一下 Vite
的威力。
快速的冷啟動(dòng)
由于是公司的內(nèi)部項(xiàng)目,不方便將源代碼上傳到 github
,所以小編只能通過(guò) gif
動(dòng)圖的方式給大家展示 Webpack
和 Vite
啟動(dòng) dev server
的過(guò)程。
Webpack
首先是通過(guò) Webpack
啟動(dòng) dev server
,過(guò)程如下:
一個(gè)規(guī)模不是很大的項(xiàng)目,dev server
啟動(dòng)完成,居然花了 25
s 左右時(shí)間。如果項(xiàng)目持續(xù)迭代變得再大一點(diǎn),那每次啟動(dòng) dev server
就是一種折磨了。
這個(gè)問(wèn)題,主要是由 Webpack
內(nèi)部的核心機(jī)制 - bundle
模式引發(fā)的。
Webpack
能大行其道,歸功于它劃時(shí)代的采用了 bundle
機(jī)制。通過(guò)這種 bundle
機(jī)制,Webpack
可以將項(xiàng)目中各種類型的源文件轉(zhuǎn)化供瀏覽器識(shí)別的 js
、css
、img
等文件,建立源文件之間的依賴關(guān)系,并將數(shù)量龐大的源文件合并為少量的幾個(gè)輸出文件。
bundle
工作機(jī)制的核心部分分為兩塊:構(gòu)建模塊依賴圖 - module graph
和將 module graph
分解為最終供瀏覽器使用的幾個(gè)輸出文件。
構(gòu)建 module graph
的過(guò)程可以簡(jiǎn)單歸納為:
獲取配置文件中 entry
對(duì)應(yīng)的 url
(這個(gè) url
一般為相對(duì)路徑);
resolve
- 將 url
解析為絕對(duì)路徑,找到源文件在本地磁盤的位置,并構(gòu)建一個(gè) module
對(duì)象;
load
- 讀取源文件的內(nèi)容;
transform
- 使用對(duì)應(yīng)的 loader
將源文件內(nèi)容轉(zhuǎn)化為瀏覽器可識(shí)別的類型;
parse
- 將轉(zhuǎn)化后的源文件內(nèi)容解析為 AST
對(duì)象,分析 AST
對(duì)象,找到源文件中的靜態(tài)依賴(import xxx from 'xxx'
) 和動(dòng)態(tài)依賴(import('xx')
)對(duì)應(yīng)的 url
, 并收集到 module
對(duì)象中;
遍歷第 5
步收集到的靜態(tài)依賴、動(dòng)態(tài)依賴對(duì)應(yīng)的 url
,重復(fù) 2
- 6
步驟,直到項(xiàng)目中所有的源文件都遍歷完成。
分解 module graph
的過(guò)程也可以簡(jiǎn)單歸納為:
預(yù)處理 module graph
,對(duì) module graph
做 tree shaking
;
遍歷 module graph
,根據(jù)靜態(tài)、動(dòng)態(tài)依賴關(guān)系,將 module graph
分解為 initial chunk
、async chunks
;
優(yōu)化 initial chunk
、 async chunks
中重復(fù)的 module
;
根據(jù) optimization.splitChunks
進(jìn)行優(yōu)化,分離第三方依賴、被多個(gè) chunk
共享的 module
到 common chunks
中;
根據(jù) chunk
類型,獲取對(duì)應(yīng)的 template
;
遍歷每個(gè) chunk
中收集的 module
,結(jié)合 template
,為每個(gè) chunk
構(gòu)建最后的輸出內(nèi)容;
將最后的構(gòu)建內(nèi)容輸出到 output
指定位置;
Webpack
的這種 bundle
機(jī)制,奠定了現(xiàn)代靜態(tài)打包器(如 Rollup
、Parcel
、Esbuild
)的標(biāo)準(zhǔn)工作模式。
然而成也蕭何敗蕭何,強(qiáng)大的 bundle
機(jī)制,也引發(fā)了構(gòu)建速度緩慢的問(wèn)題,而且項(xiàng)目規(guī)模越大,構(gòu)建速度越是緩慢。其主要原因是構(gòu)建 module graph
的過(guò)程中,涉及到大量的文件 IO
、文件 transfrom
、文件 parse
操作;以及分解 module graph
的過(guò)程中,需要遍歷 module graph
、文件 transform
、文件 IO
等。這些操作,往往需要消耗大量的時(shí)間,導(dǎo)致構(gòu)建速度變得緩慢。
開發(fā)模式下,dev server
需要 Webpack
完成整個(gè)工作鏈路才可以啟動(dòng)成功,這就導(dǎo)致構(gòu)建過(guò)程耗時(shí)越久,dev server
啟動(dòng)越久。
為了加快構(gòu)建速度,Webpack
也做了大量的優(yōu)化,如 loader
的緩存功能、webpack5
的持久化緩存等,但這些都治標(biāo)不治本,只要 Webpack
的核心工作機(jī)制不變,那 dev server
啟動(dòng)優(yōu)化,依舊是一個(gè)任重道遠(yuǎn)的過(guò)程(基本上永遠(yuǎn)都達(dá)不到 Vite
那樣的效果)。
Vite
同樣的項(xiàng)目,這次換 Vite
啟動(dòng)。
通過(guò) gif
動(dòng)圖,我們可以看到 dev server
的啟動(dòng)速度僅僅需要 2s
左右,相比 Webpack
如 ?? 爬行一樣的速度,就如同坐 ??一般,開發(fā)幸福感頓時(shí)拉滿。
Vite
之所以在 dev server
啟動(dòng)方面,如此給力,是因?yàn)樗扇×伺c Webpack
截然不同的 unbundle
機(jī)制。
unbundle
機(jī)制,顧名思義,不需要做 bundle
操作,即不需要構(gòu)建、分解 module graph
,源文件之間的依賴關(guān)系完全通過(guò)瀏覽器對(duì) ESM
規(guī)范的支持來(lái)解析。這就使得 dev server
在啟動(dòng)過(guò)程中只需做一些初始化的工作,剩下的完全由瀏覽器支持。這和 Webpack
的 bundle
機(jī)制一比,簡(jiǎn)直就是降維打擊,都有點(diǎn)欺負(fù)人了 ??。
那有的同學(xué)就會(huì)問(wèn),源文件的 resolve
、load
、transform
、parse
什么時(shí)候做呢 ?
答案是瀏覽器發(fā)起請(qǐng)求以后,dev server
端會(huì)通過(guò) middlewares
對(duì)請(qǐng)求做攔截,然后對(duì)源文件做 resolve
、load
、transform
、parse
操作,然后再將轉(zhuǎn)換以后的內(nèi)容發(fā)送給瀏覽器。
這樣,通過(guò) unbundle
機(jī)制, Vite
便可以在 dev server
啟動(dòng)方面獲取遠(yuǎn)超于 Webpack
的優(yōu)秀體驗(yàn)。
最后再總結(jié)一下, unbundle
機(jī)制的核心:
- 模塊之間的依賴關(guān)系的解析由瀏覽器實(shí)現(xiàn);
- 文件的轉(zhuǎn)換由
dev server
的middlewares
實(shí)現(xiàn)并做緩存; - 不對(duì)源文件做合并捆綁操作;
快速的熱更新
除了 dev server
啟動(dòng)外, Vite
在熱更新方面也有非常優(yōu)秀的表現(xiàn)。
我們還是通過(guò)同一個(gè)項(xiàng)目,對(duì) Webpack
和 Vite
的熱更新做一下比較。
Webpack
首先是 Webpack
在熱更新方面的表現(xiàn)。
觀察 gif
動(dòng)圖,修改源文件以后,Webpack
發(fā)生耗時(shí)大概 5
s 的重新編譯打包過(guò)程。
dev server
啟動(dòng)以后,會(huì) watch
源文件的變化。當(dāng)源文件發(fā)生變化后,Webpack
會(huì)重新編譯打包。這個(gè)時(shí)候,由于我們只修改了一個(gè)文件,因此只需要對(duì)這個(gè)源文件做 resolve
、 load
、 transfrom
、parse
操作,依賴的文件直接使用緩存,因此 dev server
的響應(yīng)速度比冷啟動(dòng)要好很多。
dev server
重新編譯打包以后,會(huì)通過(guò) ws
連接通知瀏覽器去獲取新的打包文件,然后對(duì)頁(yè)面做局部更新。
Vite
再來(lái)看看 Vite
在熱更新方面的表現(xiàn)。
觀察 gif
動(dòng)圖,可以發(fā)現(xiàn) Vite
在熱更新方面也是碾壓 Webpack
。
由于 Vite
采用 unbundle
機(jī)制,所以 dev server
在監(jiān)聽到文件發(fā)生變化以后,只需要通過(guò) ws
連接通知瀏覽器去重新加載變化的文件,剩下的工作就交給瀏覽器去做了。(忍不住要給 Vite
點(diǎn)個(gè) ???? 了。)
綜上, Vite
在 dev server
冷啟動(dòng)和熱更新方面,對(duì) Webpack
的優(yōu)勢(shì)實(shí)在是太明顯了,難怪會(huì)受到大家的青睞。
Vite 的慢
和 bundle
機(jī)制有利有弊一樣,unbundle
機(jī)制給 Vite
在 dev server
方面獲得巨大性能提升的同時(shí),也帶來(lái)一些負(fù)面影響,那就是首屏
和懶加載
性能的下降。
在本章節(jié),小編還是通過(guò)相同的項(xiàng)目為大家一一展示。
首屏性能
我們先來(lái)對(duì)比一下 Webpack
和 Vite
在首屏方面的表現(xiàn)。
Webpack
Webpack
的首屏 gif
動(dòng)圖如下:
瀏覽器向 dev server
發(fā)起請(qǐng)求, dev server
接受到請(qǐng)求,然后將已經(jīng)打包構(gòu)建好的首屏內(nèi)容發(fā)送給瀏覽器。整個(gè)過(guò)程非常普遍,沒(méi)有什么可說(shuō)的,不存在什么性能問(wèn)題。
Vite
相比 Webpack
, Vite
在首屏方面的表現(xiàn)就有些差了。
通過(guò) gif
動(dòng)圖,我們可以很明顯的看到首屏需要較長(zhǎng)的時(shí)間才能完全顯示。
由于 unbundle
機(jī)制,首屏期間需要額外做以下工作:
和 Webpack
對(duì)比,Vite
把需要在 dev server
啟動(dòng)過(guò)程中完成的工作,轉(zhuǎn)移到了 dev server
響應(yīng)瀏覽器請(qǐng)求的過(guò)程中,不可避免的導(dǎo)致首屏性能下降。
不過(guò)首屏性能差只發(fā)生在 dev server
啟動(dòng)以后第一次加載頁(yè)面時(shí)發(fā)生。之后再 reload
頁(yè)面時(shí),首屏性能會(huì)好很多。原因是 dev server
會(huì)將之前已經(jīng)完成轉(zhuǎn)換的內(nèi)容緩存起來(lái)。
- 不對(duì)源文件做合并捆綁操作,導(dǎo)致大量的
http
請(qǐng)求; dev server
運(yùn)行期間對(duì)源文件做resolve
、load
、transform
、parse
操作;- 預(yù)構(gòu)建、二次預(yù)構(gòu)建操作也會(huì)阻塞首屏請(qǐng)求,直到預(yù)構(gòu)建完成為止;
懶加載性能
Webpack
在懶加載方面, Webpack
的表現(xiàn)也正常,沒(méi)什么好說(shuō)的。
Vite
同樣的, Vite
在懶加載方面的性能也比 Webpack
差。
和首屏一樣,由于 unbundle
機(jī)制,動(dòng)態(tài)加載的文件,需要做 resolve
、load
、transform
、parse
操作,并且還有大量的 http
請(qǐng)求,導(dǎo)致懶加載性能也受到影響。
此外,如果懶加載過(guò)程中,發(fā)生了二次預(yù)構(gòu)建,頁(yè)面會(huì) reload
,對(duì)開發(fā)體驗(yàn)也有一定程度的影響。
結(jié)束語(yǔ)
盡管在首屏、懶加載性能方面存在一些不足,但瑕不掩瑜,作為目前最 ?? 的構(gòu)建工具,Vite
可以說(shuō)是實(shí)至名歸。而且這些問(wèn)題并非不可解決,比如我們可以通過(guò) prefetch
、持久化緩存
等手段做優(yōu)化,相信 Vite
未來(lái)也會(huì)做出對(duì)應(yīng)的改進(jìn)。
總的來(lái)說(shuō), Vite
還是未來(lái)可期的,還沒(méi)有開始使用的小伙伴,可以去嘗試一下噢,??。
以上就是深入剖析vite到底是快還是慢原理詳解的詳細(xì)內(nèi)容,更多關(guān)于vite快慢剖析的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue項(xiàng)目實(shí)現(xiàn)換膚功能的一種方案分析
這篇文章主要介紹了Vue項(xiàng)目實(shí)現(xiàn)換膚功能的一種方案分析,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08Vue同一路由強(qiáng)制刷新頁(yè)面的實(shí)現(xiàn)過(guò)程
這篇文章主要介紹了解決VUE同一路由強(qiáng)制刷新頁(yè)面的問(wèn)題,本文給大家分享實(shí)現(xiàn)過(guò)程,通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08Vue2.X和Vue3.0數(shù)據(jù)響應(yīng)原理變化的區(qū)別
這篇文章主要介紹了Vue2.X和Vue3.0數(shù)據(jù)響應(yīng)原理變化的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11vue mounted()函數(shù)中無(wú)法定義初始化樣式的原因分析
這篇文章主要介紹了vue mounted()函數(shù)中無(wú)法定義初始化樣式的原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03