前言
這是webpack實戰系列第12篇。
上兩篇中,描述了一些關於生產環境的配置:環境變量的使用、配置文件描述、source-map配置、資源壓縮等,從這幾個方面入手來對生產環境進行一定的配置。
本篇將從緩存
和資源bundle體積
開始,來對生產環境進行進一步的處理。
1. 緩存
緩存是指重複利用瀏覽器已經獲取過的資源。
合理的使用緩存是提升客戶端性能的一個關鍵因素。具體的緩存策略(如指定緩存時間)由服務器來決定,瀏覽器會在資源過期前一直使用本地緩存進行響應。但同時也帶來一個新的問題,比如我們想要對代碼進行一個bug fix(故障修正程序),並且立即更新到用戶的瀏覽器中,而不要讓他們使用舊的緩存資源應該怎麼處理呢?那此時最好的辦法便是更改資源的URL,這樣可迫使所有客戶端資源都去下載最新的資源。
1.1 資源hash
一個常用的方法是在每次打包的過程中對資源的內容計算一次hash,並作爲版本號存放在文件名中,如[email protected]。其中,bundle是文件本身的名字,而@後則跟隨文件內容hash值,每當代碼發生變化時,hash也會發生相應變化。
我們通常使用chunkhash來作爲文件版本號,因爲它會爲每一個chunk單獨計算一個hash值。如:
// webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
filename: '[name]@[chunkhash].js'
},
mode: 'production'
}
打包結果:
1.2 輸出動態HTML
既然資源名字使用hash動態,那麼也就意味着在HTML文件中引入的路徑也會隨之改變,而如果選擇手動處理,不光是維護成本大,而且複雜程度相當高:如果有幾十個文件變動……因此最理想的情況是打包結束後自動將最新的資源名字同步過去。此時,我們使用html-webpack-plugin來做到這一點:
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
},
output: {
filename: '[name]@[chunkhash].js'
},
mode: 'development',
plugins: [
new HtmlWebpackPlugin()
],
}
打包結果:
打包後,可以看到除了js文件之外還多出來了一個HTML文件:
index.html 內容
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Webpack App</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script src="index%4061b65a6278687c007c6c.js"></script>
</body>
</html>
從html內容可以看出,html-webpack-plugin會自動將我們打包出來的資源名放入index.html中,如上述的src="index%4061b65a6278687c007c6c.js
(其中 %40是@的編碼 ),這樣我們便不再需要手動的去更新資源url了。
HTML模板
雖然是我們通過html-webpack-plugin創建出來一個index.html文件,但是在大多數情況下,此種條件並不符合我們項目工程中的常規操作,因爲我們需要在HTML中引入一些個性化的內容,這這是,我們可以傳入一個已有的HTML模板,如:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自定義配置模板</title>
</head>
<body>
<div id="app"></div>
<p>隨便一些內容...</p>
</body>
</html>
webpack配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
template: './index.html'
})
]
}
然後再次打包,結果如下:
2. 體積監控和分析
爲保證良好的用戶體驗,我們可以對打包輸出的bundle體積進行持續的監控,以防止不必要的冗餘模塊被添加進來。
介紹兩個工具來協助我們對體積進行監控和分析。
2.1 Import Cost
在VS Code中,安裝插件Import Cost
,這個插件可以幫助我們對引入的模塊大小進行實時監測。每在我們代碼中引入一個新的模塊後,它會爲我們計算該模塊壓縮後及gzip後將佔用體積的大小。
當我們檢測到引入的某些模塊包過大時,我們可以想辦法處理它,比如尋找一些更小的包或模塊作爲替代方案,或者引入其子模塊而不是全局引入。
2.2 webpack-bundle-analyzer
作用:分析一個bundle的構成。
安裝
yarn add webpack-bundle-analyzer
// or
npm install webpack-bundle-analyzer --save-dev
配置
// webpack.config.js
const WebpackBundleAnalyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
entry: {
index: './src/index.js',
},
output: {
filename: '[name]@[chunkhash].js'
},
mode: 'development',
plugins: [
new WebpackBundleAnalyzer()
],
}
打包
執行打包命令,然後會從本地瀏覽器自動打開一個包體積監測的頁面,如下:
從上圖我們可以直觀的看到生成的 [email protected] 文件中包含的各個模塊及其佔體積佔比,這樣我們也能直觀的看出需要從某個模塊進行優化。
2.3 bundlesize 自動化監測
那剛纔所描述的只是打包後查看,如果希望自動化的對資源體積進行監控呢?bundlesize 這個工具則可以協助我們做到。
同樣,先安裝:
yarn add bundlesize
// or
npm install bundlesize
然後在 package.json 中配置:
{
"name": "w1",
"version": "1.0.0",
"main": "index.js",
"bundlesize": [
{
"path": "./src/index.js",
"maxSize": "10 kB"
}
],
"scripts": {
"test:size": "bundlesize"
}
...
}
可以看到,我設置了 bundlesize 的路徑及最大體積限制,然後在 scripts 中添加了一條腳本命令。然後在終端執行該腳本,如圖:
小結
對生產環境配置做個小結。
在開發環境中,我們注重打包速度,而生產環境中我們則關注資源輸出體積大小及如何優化客戶端緩存來縮短頁面渲染時間,通過一系列配置可以優化,如:設置環境變量、代碼壓縮、資源體積檢測監控等方法。我們也對緩存的控制有一定的瞭解,緩存的控制主要依賴於chunk內容生成hash作爲版本號,並添加到資源文件名中,使得資源更新後客戶端可以及時更新最新資源。
此外,source map主要用於線上問題的追溯,不過存在安全隱患,可以通過一些特殊的配置來兼顧追溯及安全問題。
描述完了生產環境配置,那麼下一階段來到打包優化問題。