藉助 wepack 的 hash
命名法,不僅可以提高我們專案的構建效率,在生產環境中,合理設定 hash
型別有助於我們對資源進行有效的快取。
webpack hash 種類
當無情面試官問 webpack 有幾種 hash 型別?
-
hash
- 工程級如果出口檔案設定的型別是
hash
則每次修改任何檔案,所有檔名的hash
都會跟著改變。(不能有效利用快取) -
chunkhash
- 模組級根據不同的入口檔案進行依賴檔案解析、構建對應的
chunk
,生成對應的hash
值。 -
contenthash
- 檔案內容級由檔案內容產生的
hash
值,內容不同產生的contenthash
值也不一樣。
如何設定 hash
達到專案優化的目的?
js 檔案分類構建,設定 chunkhash
首先使用 CommonsChunkPlugin
外掛提取第三方庫和公眾模組,進行單獨打包構建:
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
]
接著我們在 output
對 filename
和 chunkFilename
兩個欄位設定 chunkhash
,生成對應 hash
值:
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'js/[name].[chunkhash].js',
chunkFilename: 'js/[id].[chunkhash].js' // chunkFilename 是處理非同步模組的
},
通過設定 chunkhash
最後打包出來的 js
檔案會生產三種 chunkhash
:
- 正常引入的
js
檔案對應的hash
- 非同步載入的
js
檔案(如果在專案中存在的話)對應的hash
- 提取的三方庫和公共模組對應的
hash
那麼只要對應的 js
檔案程式碼不改動,就可以保證其 chunkhash
值不會受影響,從而達到瀏覽器的持久快取。
抽離 css,設定 contenthash
首先,使用 ExtractTextPlugin
外掛將所有的入口 chunk
中引用的 *.css
,抽離到獨立的 css
資料夾中。
抽離之後的樣式將不再內嵌到 JS bundle 中,而是會放到一個單獨的 CSS 檔案當中,如果樣式檔案大小較大,這會做更快提前載入,因為 CSS bundle 會跟 JS bundle 並行載入。
plugins: [
new ExtractTextPlugin({
filename: 'css/[name].css',
allChunks: true
}),
]
之後對 css 檔案進行 contenthash
命名:
plugins: [
new ExtractTextPlugin({
filename: 'css/[name].[contenthash].css',
allChunks: true
}),
]
針對 css
檔案會生產對應的 contenthash
值,只要 css
檔案內容沒有修改,那麼 contenthash
值就一直保持不變,以有效的利用瀏覽器快取。
css 檔案可以設定成 chunkhash
嗎?
答案是不要這麼做,因為 chunkhash
是模組級,我們是將樣式作為模組 import
到 js
檔案中,所以它們的 chunkhash
是一致的。
即 js
和所引入的 css
共用同一個 chunkhash
,只要 js
改變,與其關聯的 css
檔案對應的 chunkhash
值也會改變,但可能其內容並沒有改變,所以達不到快取的效果。
這是 「效能優化小冊」
系列第二篇小記,歡迎關注。