隨着Babel、TypeScript、VueLoader、Terser等編譯、轉譯技術的大規模使用,Webpack的編譯時間正不斷膨脹。爲了優化編譯速度,社區主要有兩種方案:javascript
經過把loader的處理結果緩存到本地磁盤,來加速二次編譯java
經過預編譯dll讓webpack跳過一些模塊的編譯,來加速編譯webpack
這些方案在必定程度上解決了編譯速度慢的問題,但隨之而來的是成堆的配置,嚴重影響了Webpack的使用體驗,甚至出現了「Webpack配置工程師」這種「新職業」。git
與此同時,社區出現了一些新興的編譯技術,好比Snowpack,它使用瀏覽器原生的ES Module實現了O(1)時間的編譯,對於「苦Webpack久已」的那些人來講簡直不要太有吸引力。github
可是這對Webpack來講是一種挑戰,面對可能會被蠶食的用戶市場,Webpack5的內置緩存方案終於出來了。web
長效緩存是瀏覽器層面的緩存,Webpack經過optimization的splitChunks和runtimeChunk的配置,讓編譯輸出的文件具備穩定的hash名稱,從而讓瀏覽器能長期有效、安全的複用緩存,達到加速頁面加載的效果。數據庫
編譯緩存是編譯時的緩存,Webpack經過在首次編譯後把結果緩存起來,在後續編譯時複用緩存,從而達到加速編譯的效果。npm
Webpack5的內置緩存,以及本文所討論的,都是指編譯緩存。瀏覽器
在使用Webpack4以及以前的版本時,咱們都會注意到這樣的現象:緩存
代碼熱更新很快
npm run star慢
npm run build慢
這種現象的本質是:Webpack4在運行時是有緩存的,只不過緩存只存在於內存中。因此,一旦Webpack的運行程序被關閉,這些緩存就丟失了。這就致使咱們npm run start/build的時候根本無緩存可用。
因此,解決問題的辦法就是把這些Webpack編譯過程當中的產生的緩存持久化到本地磁盤、數據庫或者雲端。這裏面涉及到兩點:要持久化什麼,持久化到哪裏。
Webpack自己就已經有一套緩存方案,只是不夠完善,不支持持久化。站在如今的角度來看,咱們應該直接去完善Webpack核心代碼,補充上持久化緩存的功能,使用一套緩存方案解決全部問題,這是顯而易見的。
然而,當時社區好像沒搞清楚「要持久化什麼」這個問題, 他們沒有在Webpack核心代碼上發力,而是選擇了從外部解決。因而就出現了cache-loader、dll等技術,雖然在必定程度上解決了問題,但卻引入了過多的複雜性。
實際上,「要持久化什麼」這個問題從一開始就是顯而易見的:是Webpack運行時存在於內存中的那些緩存,不是loader的產物,更不是dll。所以,Webpack5提供了一套持久化抽象,並提供了幾個實現:
IdleFileCachePlugin:持久化到本地磁盤
MemoryCachePlugin:持久化到內存
根據Webpack運行環境的不一樣,在dev開發時依舊使用MemoryCachePlugin,而在build時使用IdleFileCachePlugin。
Webpack5直接從內部核心代碼的層面,統一了持久化緩存的方案,有效下降了緩存配置的複雜性。除此以外,因爲全部被webpack處理的模塊都會被緩存,咱們npm run start/build的二次編譯速度會遠超cache-loader,同時dll也能夠退出歷史舞臺了。
Webpack4時之因此要有dll,是由於cache-loader並不能覆蓋全部模塊,只能對個別被loader處理的模塊進行緩存。而那些通用的庫是無法被cache-loader處理的,因此只能經過dll的方式來預編譯。
實際上,Webpack5的內置緩存方案不管從性能上仍是安全性上都要好於cache-loader:
性能上:因爲因此被webpack處理的模塊都會被緩存,緩存的覆蓋率要高的多
安全上:因爲cache-loader使用了基於mtime的緩存驗證機制(參考:juejin.im/post/5ebe25…),致使在CI環境中緩存常常會失效,可是Webpack5改用了基於文件內容etag的緩存驗證機制,解決了這個問題。
具體使用的Webpack5配置官網已經給出了:webpack.js.org/configurati…
Webpack4能用上Webpack5的緩存方案嗎?
可使用hard-source-webpack-plugin,它就是基於上述Webpack5的實現思路的一個插件。可是在#troubleshooting中也能夠看到,這裏面可能會有一些坑。
Snowpack、Vite這種庫能夠替代Webpack嗎?
基於Webpack當前龐大的生態,以及Webpack5將要帶來的game-changer級別的模塊聯邦功能,我認爲是不能的,可是這種基於瀏覽器原生ES Module的技術可能會被Webpack採用。