移動端項目,需要嚴格控制包的大小,不然影響用戶體驗,所以需要對webpack進行優(yōu)化
本文檔主要介紹自己初次體驗webpack優(yōu)化的一些知識點。
敲黑板
包分析工具
vue-cli內(nèi)置包分析工具
// webpack.prod.conf.js
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
可以通過在package.json添加命令開啟包分析工具,默認8888端口
"analyze": "NODE_ENV=production npm_config_report=true npm run build"
vue-cli 默認配置 打包思路
vue-cli默認配置將node_modules里的依賴都打進vendor中,有一些弊端
- 引入的模塊越多,
vendor文件越大 - 提取公共文件目的是,一次打包,之后文件盡可能被瀏覽器緩存下來,不能每次打包都去改變hash值
- 這個vendor文件將
node_modules中所有依賴都進行抽離,之后維護如果添加新的模塊或者刪除一些沒有用的模塊,那么vendor的hash值會發(fā)生變化,不利于瀏覽器緩存
項目中,我主要通過CommonsChunkPlugin插件對webpack進行優(yōu)化,將本來1M的包,最后只有300+kb
CommonsChunkPlugin
- 會將項目中引入的
node_modules中的模塊抽離出來
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// this assumes your vendor imports exist in the node_modules directory
return module.context && module.context.includes('node_modules');
}
});
- 提取公共模塊,如果沒有添加或者刪除公共模塊,則hash值不變,首次加載被瀏覽器緩存
- 盡量將項目中不變的依賴包 抽離出一個文件,保證后續(xù)引入別的依賴包,此文件hash值不變化
- 下圖中將
vue vuex vue-router vant繼續(xù)抽離出一個文件
代碼如下,兩種寫法
// 方法一 對module.context進行過濾
new webpack.optimize.CommonsChunkPlugin({
names: "common",
minChunks: function(module, count) {
if (module.resource && /^.*\.(css|scss)$/.test(module.resource)) {
return false;
}
return module.context &&
(module.context.includes("vue") ||
module.context.includes("vant") ||
module.context.includes("vuex") ||
module.context.includes("vue-router"));
}
}),
// 方法二
// webpack.base.conf 文件 將公共模塊,寫入入口
entry: {
app: './src/main.js',
common: ['vue', 'vuex', 'vue-router', 'vant']
},
// webpack.prod.conf
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
minChunks: Infinity // 除了入口的模塊,其他模塊都不打包進入common
}),
修改router,目的修改打包之后的js文件,便于跟蹤
通過下面對每個路由進行修改,添加webpackChunkName,打包出來每個模塊的js名稱會根據(jù)自己設(shè)定的來
除此之外,還需要同步修改webpack.prod.conf.js中output的配置
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[name].[chunkhash].js')
},
component: () => import(/* webpackChunkName: "home" */ '@/containers/home.vue'),

image.png
對minChunks理解
當entry屬性的值為對象時,作為多個入口的文件們,每個都是一個chunk
minChunks:number
某個模塊最少被多少個入口文件依賴,當大于等于設(shè)定的值,就會被打入公共包,小于這個值,該模塊就會被和每個入口打包在一起
minChunks:infinity
不會把任何依賴的模塊提取出來打入公共包
minChunks:默認值
如果沒有設(shè)置,則為默認值,只有被所有入口文件所依賴,則提取出來打公共包
代碼分割
- 分離業(yè)務(wù)代碼和第三方庫 (vendor)
- 按需加載 (利用路由中 import() 語法 component: () => import('@/components/Hello'))
- 首頁首次加載的時候如果不需要就不加載,等加載到響應(yīng)路由再去加載相關(guān)資源
- 減少首屏加載時間
- 根據(jù)模塊的相對路徑生成一個四位數(shù)的hash作為模塊id
- webpack里每個模塊都有一個module id
- HashedModuleIdsPlugin 模塊根據(jù)相對路徑生成一個四位數(shù)hash作為模塊id,引入新的模塊,不影響module id,只要模塊路徑不改變
new webpack.HashedModuleIdsPlugin()
參考文章
webpack
commonsChunkPlugin
demo
希望此文對大家有幫助,歡迎吐槽