上一篇咱們講到,webpack3.x 升級 4.x 時遇到的問題、緣由和解決方案,今天講一下 webpack 4.x
的打包優化。node
在優化以前咱們須要清楚項目的打包狀況,npm run build
後 webpack
會將打包信息打印到終端,像這樣:webpack
可以看到有好幾個文件比較大,可是並不清楚具體包含哪些模塊,哪些模塊適合單獨提取,哪些模塊不適合提取,這個時候就須要用到打包分析的工具。nginx
如下摘自 webpack 文檔:git
Bundle Anlysis - 打包分析github
一旦開始分割代碼,分析輸出以檢查模塊在哪裏結束將頗有用。official analyze tool 是一個很好的起點。 還有一些其餘社區支持的選項:web
- webpack-chart: 用於 webpack 統計信息的交互式餅圖
- webpack-visualizer: 可視化和分析您的包,以查看哪些模塊正在佔用空間,哪些多是重複的。
- webpack-bundle-analyzer: 一個插件和 CLI 實用程序,將包內容表示爲方便的交互式可縮放樹形圖。
- webpack bundle optimize helper: 此工具將分析您的捆綁包,併爲您提供切實可行的建議,以進行改進以減少捆綁包的大小。
- bundle-stats: 生成捆綁報告(捆綁大小,資產,模塊),並比較不一樣版本之間的結果。
這裏咱們使用的是 webpack-bundle-analyzer
,交互式可縮放樹形圖,便於咱們對打包狀況有一個比較直觀的瞭解。npm
安裝插件element-ui
npm i -D webpack-bundle-analyzer
複製代碼
引入插件瀏覽器
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
module.exports = {
plugins: [new BundleAnalyzerPlugin()],
};
複製代碼
而後咱們再試着構建如下,看會怎麼樣緩存
npm run build
複製代碼
插件會自動在瀏覽器中打開連接:http://127.0.0.1:8888/ ,以交互式可縮放樹形圖展現了當前項目的打包狀況,能夠清楚的看到各個文件包含的模塊,針對性的處理:
分析上面 👆 的樹形圖,概括瞭如下幾個能夠優化的點:
將 optimization.splitChunks
屬性的默認值刪除,而後在 cacheGroups
中配置以下:
webpack.prod.js
// ..
const webpackConfig = merge(baseWebpackConfig, {
// ..
optimization: {
splitChunks: {
- chunks: "async",
- minSize: 30000,
- maxSize: 0,
- minChunks: 1,
- maxAsyncRequests: 5,
- maxInitialRequests: 3,
- automaticNameDelimiter: "~",
- automaticNameMaxLength: 30,
- name: true,
cacheGroups: {
+ common: {
+ test: /[\\/]node_modules[\\/]/,
+ name: 'vendors-common',
+ minSize: 0,
+ minChunks: 2, // 最少被2個chunk引用
+ chunks: 'initial',
+ priority: 1 // 優先級,默認是0,能夠爲負數
+ },
+ other: {
+ test: /[\\/]node_modules[\\/]/,
+ name: 'vendors-other',
+ chunks: 'initial',
+ priority: -10
+ },
- defaultVendors: {
- test: /[\\/]node_modules[\\/]/,
- priority: -10
- },
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
// ..
});
// ..
module.exports = webpackConfig;
複製代碼
咱們再次構建,看看
npm run build
複製代碼
能夠看到拆分出了幾個包含 node_modules
的大文件:
swiper
,單個組件中引入的依賴,webpack
會自動提取)比較一下代碼拆分先後的兩個入口加載文件大小的不一樣:
入口 2 沒有變化,入口 1 的加載文件大小減小的 0.62MB
,縮小將近 25%
,固然這是沒有進行 gzip
壓縮的狀況,在 nginx
服務器上啓用 gzip
壓縮總體大小會更小,這裏就不展開了
若是你想單獨將某些依賴,單獨提取出來,能夠看看官方的這個例子,若是你的項目依賴較少,你徹底能夠按你喜歡的組合,手動拆分你的項目依賴到多個文件中。
當訪問網頁時,請求的文件會存儲在瀏覽器的緩存中,當下次再訪問時,若是知足HTTP 緩存機制,瀏覽器能夠從緩存中讀取文件,而沒必要從服務器讀取,甚至不用發起請求,能夠顯著提高加載速度並減小流量消耗。
可是若是項目從新構建,而用戶瀏覽器中的緩存還未過時,想要快速更新並繼續保留部分緩存,該怎麼作呢?
更多細節請看,HTTP 緩存-廢棄和更新緩存的響應
對此 webpack
打包須要優化一下幾點:
webpack.prod.js
// ..
const webpackConfig = merge(baseWebpackConfig, {
// ..
output: {
// ..
- filename: utils.assetsPath('js/[name].[chunkhash].js')
+ // 根據文件內容生成的 hash,文件內容改變時 hash 也隨之改變
+ filename: utils.assetsPath('js/[name].[contenthash].js')
},
optimization: {
+ // 運行時塊包含模塊間的引用關係,將它提取出來做爲單獨的文件,引用關係發生改變時,不會致使無關的文件內容發生改變
+ runtimeChunk: 'single',
+ // 由於使用 hashed,當本地新增或減小依賴時,不會影響其餘模塊的 ID(默認狀況下 ID 的值是根據解析順序遞增的)
+ moduleIds: 'hashed'
// ...
}
});
// ..
module.exports = webpackConfig;
複製代碼
更多細節請看,webpack 文檔-緩存(快取)
代碼拆分的過程當中,有嘗試過基於現有配置的基礎上,單獨拆分出指定依賴(如 Element-UI
,由於不常改動且文件較大),可是會破壞現有的拆分,屢次嘗試以後無果,最接近的時候是這樣的,入口 1 會將其包含在文件中,可是入口 2 不會,當前項目有兩個入口:
採用以下配置:
// ..
const webpackConfig = merge(baseWebpackConfig, {
// ..
optimization: {
splitChunks: {
cacheGroups: {
common: {
- test: /[\\/]node_modules[\\/]/,
+ test: /[\\/]node_modules[\\/]((?!(element-ui)).)+[\\/]/,
name: 'vendors-common',
minSize: 0,
minChunks: 2, // 最少被2個chunk引用
chunks: 'initial',
priority: 1 // 優先級,默認是0,能夠爲負數
},
other: {
- test: /[\\/]node_modules[\\/]/,
+ test: /[\\/]node_modules[\\/]((?!(element-ui)).)+[\\/]/,
name: 'vendors-other',
chunks: 'initial',
priority: -10
},
+ 'element-ui': {
+ test: /[\\/]node_modules[\\/](element-ui)[\\/]/,
+ name: 'vendor-element-ui',
+ chunks: 'initial',
+ priority: -15
+ },
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
// ..
});
// ..
module.exports = webpackConfig;
複製代碼
後續有處理方案後會更新,到這裏打包大小優化就告一段了,下一篇會講講如何對打包速度進行優化。