1. 熱模組替換(Hot Module Replacement, HMR)
首先,讓我們聊聊熱模組替換(HMR)。簡單來說,當你修改了一個檔案,比如一個元件或者一個函式,然後儲存,這時候你希望瀏覽器裡的應用能夠自動更新顯示最新的變化,而不是每次都得手動重新整理頁面。這個功能就叫 HMR。
Webpack 的 HMR 實現方式是這樣的:當某個模組發生變化時,Webpack 會嘗試只更新這個模組,而不會重新載入整個頁面。但是有時候這個過程並不完美,尤其是對於複雜的依賴關係,可能會導致整個頁面都需要重新載入。
Vite 則使用了一種更現代的方法來實現 HMR。它基於原生的 ES Modules 動態匯入特性 (import()) 來實現。這意味著當一個模組發生變化時,Vite 可以非常精確地知道哪些部分需要更新,哪些不需要,從而只更新真正改變了的部分。這種方式更加高效,幾乎感覺不到延遲。
2. 開發伺服器啟動時間
再來談談開發伺服器啟動的時間。當你第一次啟動專案時,開發伺服器需要做很多工作,比如解析所有的模組依賴,生成中間程式碼等。這一步驟對於大型專案來說可能會花費不少時間。
Webpack
在啟動時會進行一個完整的構建過程,包括預解析所有模組的依賴關係。這樣做雖然有助於生產環境下的最佳化,但是在開發環境中會導致啟動時間變長。特別是對於一些依賴檔案很多或是關係複雜的大型專案,webpack的這種“不構建完不給看”的死腦筋做法會導致啟動時間變得相當長。
Vite
則採用了不同的策略。它不會一開始就構建整個專案,而是採用按需編譯的方式。也就是說,只有當瀏覽器請求某個檔案時,Vite 纔會去編譯這個檔案。
sayHello.js:
export default function sayHello() { console.log('hello world'); }
main.html:
<script type="module"> import hello from './sayHello.js'; sayHello(); // hello world </scirpt>
就拿上面這段程式碼來說,瀏覽器(當然得是支援ES module的瀏覽器)在執行到 import hello from './sayHello.js';
之前甚至都不知道還有這麼個東西存在,只有到這一行纔會去傳送請求。這樣一來,開發伺服器可以在很短的時間內啟動起來,等到你開始瀏覽專案的時候,Vite 就會一邊載入一邊編譯檔案,使用者體驗非常好。
爲了各位看官老爺能夠更加清晰理解這一點,就舉個很現實的例子。各位去下館子的時候,要是後廚爲了上菜好看,或者是餐桌上真就有一個這麼掃興的人,必須等菜都上齊了之後拍完照才能吃的話,想必各位都得暗暗不爽,但要是上一道吃一道,對於我這種吃貨來說無疑是極好的,而這也就是webpack和vite的區別。
3. 網路的併發請求
據不可靠訊息,webpack在開發之處就試圖去像如今的vite一樣做成按需引入的效果,但苦於當時還處於http1時代,單個域名併發請求撐死也就是六七個,再多的話就會造成阻塞的問題,所以不得不去減少打包後的產物從而避免http的阻塞。但是隨著不斷的發展完善,現如今的http2已經沒有了當年的併發限制,所以這也是vite利用rollup去把打包產物分為多個小模組的前提條件。
4. 開發過程
除了剛剛提到的那些技術方面的差異,開發人員對於開發過程也有影響,以前頁面簡單,折騰來折騰去無非就是css,html,圖片之類的檔案。但是還明顯現在已經不止於這些東西了,音訊,gif動畫,ts語言,圖片壓縮等各式各樣的檔案甚至是3D模型都往上面放,而webpack又得依靠不同的loader去把它們解析成js模組。這就好比西餐切魚,切肉,切菜,切水果都得用不同的刀,而中餐則是一把帶蒜味的菜刀就足以砍遍菜市場。於是這就造成webpack不得不頻繁切換使用各類loader,而vite則是更傾向打造更加“鋒利且多功能的中式菜刀”
5. 構建最佳化
最後,我們來看看構建最佳化方面的一些差異。
Webpack 是一個非常強大的工具,在上一篇文章中我用“菜刀和鍋”的例子去給各位提到了webpack中的plugin以及loader,在它們的幫助下,webpack可以像切菜炒菜一樣處理各種型別的資源,比如 CSS、JavaScript、圖片等等。但是這種靈活性也帶來了配置的複雜性,有時候可能會導致較大的輸出檔案和較長的構建時間。也就是說無論是“刀鈍了”還是“鍋漏了”,甚至是隻要一個地方由於檔案過大或是其他雜七雜八的原因卡住了,都會導致整個專案的構建速度大大下降。
不僅如此,webpack是基於node去執行的,雖說現在node在處理多工的時候並不會比Java,c等多執行緒語言慢太多,但js作為單執行緒語言依舊是無法很好的利用到CPU的多核優勢,所以構建速度也會相應的變慢。
Vite 在生產構建時使用了 Rollup,這是一個專門為現代 JavaScript 應用設計的打包工具。Rollup 非常擅長處理 ES Modules,並且能夠生成更小的檔案大小和更快的構建速度。Vite 結合了 Rollup 的優勢,使得最終的打包結果既快速又輕量。
並且不同於webpack基於js的執行方式,vite無論是預構建還是按需編譯的過程都是透過go語言編寫的esbuild去執行的,多執行緒語言能夠充分發揮CPU的多核優勢,從而大幅度提升速度。
總結
綜上所述,Vite 之所以能夠在打包速度上勝過 Webpack,主要是因為它採用了更現代的技術棧,比如 ES Modules 的動態匯入,以及更高效的 HMR 實現。此外,Vite 在開發伺服器啟動時採用的按需編譯策略,以及生產構建時使用 Rollup 進行最佳化,這些因素共同作用使得 Vite 成爲了一個非常快速的開發工具。希望本文能幫助你更好地理解 Vite 與 Webpack 在打包速度上的差異,並根據專案需求選擇合適的構建工具。最後祝各位讀者姥爺0 waring(s),0 error(s)。