在前端領域中,bundle是很重要的,dev build跟production build大小,我舉例手上的專案,9mb -> 3xx kb(gzip)。
關於檔案大小的部份不在此介紹中。這應該是比較簡單的part,只要你mode有開prodction應該就差很多了。 (好吧 我想寫caching 上集晚點補)
靜態檔案cache是一個很重要的機制,cache的好,使用者不用每次進網頁都載一次檔案。這點在前端蠻容易被忽略的(至少對於我本人)。在本地端開發的時候很少會感受到file size的影響,上了production習慣開dev tool + disable cached。
cache通常會提到server設定,不過我們這邊要提的如何讓webpack做long term cache
首先要知道的就是一般使用webpack output file會長這樣
output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, '../dist'),
},
為什麼要加hash
基於正常使用者不會每次進入頁面都clean cached,若是今天線上版的foo.js要更新
client端看到foo.js名稱一樣使用舊的cache,後果不堪設想。(頁面極度容易掛掉)
所以每次build的時候依據檔案的內容產生不一樣的的md5加在後面,client端看到不一樣的檔案名稱就會抓取新的檔案
為啥不用 static.file?v=xx.xx.xx 可以看參考
好解法=使用hash file name 先佈static file再佈頁面
這是如果有使用cdn之類的功能的話,如果是docker一起丟file+html是沒差的
請視狀況而定
long term caching講的是如何在每次佈版的時候,只針對最少的js改動(其他保留不變)
了解這兩個的差異是開始的第一步
不過自行了解一下code splitting(我好像沒介紹)
對於hash,計算所有chunks的hash,也就是所有檔案後面接的hash會一樣
對於chunkhash,每個chunk單獨計算hash
不用在dev放上hash,會增加build的時間
我們希望當只有一個檔案更新的時候使用者只需要抓一個檔案,想當然要用chunkhash
至於有使用ExtractTextPlugin的人可以google一下content-hash
因為我們在新的專案使用styled components所以沒有這個問題
這麼簡單的結束了嗎(X)
實際在做旳時候,就算是某檔案完全沒更動也是換了hash value。
上網查了後,我們還需要了解manifest與runtime
webpack在連接所有的code與module相依時(js load完了沒,這module需要啥其他module),會需要一段code來做這些事情,而這段code就稱之runtime
當你寫著import, require,compile之後會變成webpack的module,在code裡面常常看到樣的code
__webpack_require__(id) // <<< id
而什麼module對應什麼id這些就是manifest做的
當你新增或刪除module, module排列的id會變動,這些東西寫在chunk裡面每次就需要rebuild。
在webpack4中,可以設置runChunk: true,會將runtime與manifest拉出來(each entry has a runtime)
這樣可以確保剩下的code之中不會挾雜其他的module id
webpack 4.x 沒有 CommonsChunkPlugin
另外對於manifest,拉出來還不夠看。
webpack預設module是name by id(integer)
假設現在有 1 , 2 , 3, ,4 ,5 module
插入了新的module被歸類在3
1不變, 2不變, 3 new, 4 -> original 3, 5 -> original 4, 6, -> original 5
這樣子就rebuild了original 3, 4, 5
所以我們還會引入NamedModulesPlugin, HashedModuleIdsPlugin
一樣是用內容轉成hash,就算上述的事情發生,只需要build new or modified module and rebuild runtimeChunk使用者也不用重新loading file
最後的配置(簡單的)
output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, '../dist'),
},
optimization: {
runtimeChunk: true, // this line
splitChunks: {
chunks: 'async',
name: true,
cacheGroups: { // can do more if you have complex SPA
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
components: {
test: /[\\/]components[\\/]/,
name: 'components',
chunks: 'all'
}
}
}
},
plugins: [
new webpack.HashedModuleIdsPlugin(), // this line
],
想知道更深的進去參考挖吧