vue2项目webpack3.x打包文件分割优化加载
- 0. 项目目录和依赖信息
- 1. 开启 gzip(建议)
- 2. vue2项目配置懒加载(建议)
- 3. 拆分 vendor 包
- 注意:webpack3使用CommonsChunkPlugin实现
本文使用 3 种方案进行叠加优化
优先级按以下排序。
0. 项目目录和依赖信息
package.json
部分信息如下:
{
"scripts": {
"build": "node build/build.js"
},
"dependencies": {
"vue": "^2.6.14",
"vue-router": "^3.5.2",
"vuex": "^3.6.2"
},
"devDependencies": {
"webpack": "^3.12.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.11.5",
"webpack-merge": "^4.1.0",
"webpack-post-compile-plugin": "^0.5.1",
"webpack-transform-modules-plugin": "^0.3.5"
}
}
1. 开启 gzip(建议)
-
打开Nginx配置文件:
通常,Nginx的主配置文件位于/etc/nginx/nginx.conf
。但实际的配置文件可能还包含在其他位置,例如/etc/nginx/conf.d/*
或/etc/nginx/sites-available/*
。 -
编辑配置文件:
在http、server或location块中添加以下指令来启用gzip压缩:
http {
...
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_compresss_level 9;
gzip_vary on;
...
}
- 重新加载Nginx
nginx -s reload
webpack.prod.config.js
配置 gzip
config: {
// ...
build: {
// ...
productionGzip: true,
productionGzipExtensions: ['js', 'css']
// ...
}
// ...
}
5. 打包后会生成 *.gz的文件如下,nginx 会优先加载 gz 文件
2. vue2项目配置懒加载(建议)
- 在路由上配置懒加载方式。当请求新页面时再进行网络请求加载资源
// router/index.js
export defalut new Router({
base: '/',
mode: 'hash',
routes: routes
})
// main.js
import router from './router'
Vue.use(router);
new Vue({
// ...
router,
// ...
})
- 实现的效果如下图,网络请求实现了懒加载方式
每请求一个页面,加载一个页面资源 js,这样的好处是拆分 app.js ,全局实现懒加载后,大大的减少app.js 包的体积,加速首屏加载和渲染。
- 组件懒加载
// 如果发现了一个文件特别大,分析引入的组件是否太大,可以做成异步组件,拆分出一个文件
components: {
OrgSelect: () => import( '@/components/org-select.vue')
},
3. 拆分 vendor 包
由于项目第三方的依赖包会越来越多,因为 vendor 包会越来越大(未进行 gzip 情况下一般都有 2M 或以上),首次加载会占用很长时间。此时可以考虑把其他第一方的组件库独立打包,如 echart
,vant
,loadsh
,moment/dayjs
等
注意:webpack3使用CommonsChunkPlugin实现
Webpack 4及更高版本提供了一个名为SplitChunksPlugin
的内置插件,用于自动拆分公共的依赖模块到已有的入口chunk中,或者提取到新的生成的chunk
// webpack.prod.config.js
module.exports = {
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// 匹配 node_modules 下的模块
return module.context && module.context.includes('node_modules');
}
}),
// 从 vendor 中提取出 echarts
new webpack.optimize.CommonsChunkPlugin({
name: 'echarts',
chunks: ['vendor'],
minChunks: function(module) {
return module.resource && /echarts/.test(module.resource)
}
}),
// 从 echarts 中提取出 echarts-component
new webpack.optimize.CommonsChunkPlugin({
name: 'echarts-component',
chunks: ['echarts'],
minChunks: function(module) {
return module.resource && /component/.test(module.resource)
}
}),
// 从 vendor 中提取出 vant
new webpack.optimize.CommonsChunkPlugin({
name: 'vant',
chunks: ['vendor'],
minChunks: function(module) {
return module.resource && /vant/.test(module.resource)
}
}),
// 从 vendor 中提取出 monent / dayjs 合成一个文件
new webpack.optimize.CommonsChunkPlugin({
name: 'moment',
chunks: ['vendor'],
minChunks: function(module) {
return module.resource && (/moment/.test(module.resource) || /dayjs/.test(module.resource))
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: Infinity, // 默认是 3 的,设置成无限大,实现一个异步一个块
}),
// 从 app 中提取出 app-components
new webpack.optimize.CommonsChunkPlugin({
name: 'app-components',
chunks: ['app'],
minChunks: function(module) {
return module.resource && /components/.test(module.resource)
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
]
// 其他配置...
};
// 配置插件,由于分割了很多包,所以手动设置一下加载次序
new HtmlWebpackPlugin({
// 这里要调整成手动排序 chunk
chunksSortMode: 'manual',
// 把我们自己分割好的包的 chunk 名一个个按顺序记录在这里,不然打包会报错
chunks: [
'manifest',
'vendor',
'echarts',
'echarts-component',
'vant',
'moment',
'app-components',
'app'
]
}),
加载效果如下:
参考: https://juejin.cn/post/7117450435920674829