vue中关于webpack优化的一些坑
前言
最近闲来无事,就想着优化下一个pc端的老项目,首屏加载时间有点久,就想着用webpack分包,懒加载等方式优化下,踩了不少的坑,发出来记录下。
webpack分包
原理
webpack分包其实并不能改变整体打包的体积大小,那有啥作用捏。在默认打包规则下,node_modules下的npm包会整体打包出来一个叫chunk-vedors的js文件,分包其实就是把这整个js文件拆分。举个栗子,就是一个打包后10M的chunk-vedors的js文件,首屏加载可能需要1s,但是如果拆分成两个5M的js文件,因为浏览器可以并行下载,可能全部下载完只需要0.5s,这样就减少了白屏时间啦。
准备工作
首先为了更直观地表示打包后文件大小,我们可以通过webpack-bundle-analyzer这个包实现打包后文件大小可视化。
//npm安装
npm install webpack-bundle-analyzer
//引入插件
//vue.config.js
module.exports = {
chainWebpack: (config) => {
config.plugin("webpack-bundle-analyzer").use(require("webpack-bundle-analyzer").BundleAnalyzerPlugin);
}
}
配置完成后打包,会自动弹出一个网页,可以很直观地看出打包后文件的大小。
我们发现chunk-vedors这个js文件大小有1.61m,里面包含npm的各种包。
分包路径问题
接下来就是对chunk-vedors进行分包,尝试把其中最大的ivew组件库分出来。 这时候坑来了,当我按照网上配置分包时,发现不起作用。
//vue.config.js
module.exports = {
configureWebpack: {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
iview: { // 分离组件库
name: 'view-design',
test: /[\\/]view-design[\\/]/,
priority: 0,
chunks: 'all',
},
},
}
},
},
}
//网上的配置,不起作用
经过仔细观察,才发现网上打包后iview的路径名和自己打包出来的并不一样。(有可能是版本或者配置不同)
别人打包出来iview路径是view-design。
而我的路径则是_view-design@4.7.0@view-design\dist
遂更改匹配的路径
//vue.config.js
module.exports = {
configureWebpack: {
optimization: {
splitChunks: {
chunks: 'all',//表明将选择哪些 chunk 进行优化
cacheGroups: {
iview: {
name: 'view-design',//组件名称
test: /[\\/]_view-design@4.7.0@view-design[\\/]dist[\\/]/,//匹配路径
priority: 0,//优先级
chunks: 'all',
},
},
}
},
}
成功分包
可以看到原来1.61M的chunk-vendors的js文件分成了两个js文件,view-design组件库成功从chunk-vendors里面分离出来。分包后首页白屏问题
当我们成功分包后,打包并打开项目,发现居然白屏了,渲染不出任何东西,控制台有一个warning提示。
上网查找解决方法,原来是要在index里面配置chunks这个数组,要将分出来的包名称加到这个数组中去。
//vue.config.js
module.exports = {
page: {
index: {
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ["chunk-vendors", "chunk-common", "index", "view-design"],//添加分出来的包
},
}
}
修改后重新打包即可成功运行!
减少moment包大小
moment这个包里面有很多语言包,我们可以删除大部分只留下中文语言包。
这个倒是没什么坑,按照网上的教程配置即可
//npm安装
npm install moment-locales-webpack-plugin -D
//vue.config.js
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
module.exports = {
configureWebpack: {
plugins: [
new MomentLocalesPlugin({localesToKeep: ['zh-cn']})
]
}
}
删除语言包后,大小从673KB减少到174KB
路由懒加载
路由懒加载比较简单,在路由中使用es6的import懒加载() => import()即可实现。
//简单的例子
//router/index.js
const router = new Router({
routers: [
{
path: '/login',
component: () => import('@/components/login/Login');
}
]
})
每个 () => import() 都会生成一个独立的JS文件,告诉 webpack 这就是一个代码分割点,这样生成一个独立的js文件,实现按需加载的功能。
但是配置完成后我们会发现在首屏加载的时候依然会把所有的路由文件加载出来,并没有实现懒加载。
首次加载依然会加载全部路由文件
经过网上一番查阅才发现vue-cli会把懒加载的路由设置成prefetch,即预先加载的资源,会在一开始就预加载所有的路由。关键字prefetch作为元素link的属性rel的值,是为了提示浏览器,用户未来的浏览有可能需要加载目标资源,所以浏览器有可能通过事先获取和缓存对应资源,优化用户体验。
——mdn对于prefetch的解释
打包后index.html文件中路由文件都加上了rel=prefetch
预加载的问题
网上搜索解决方法,发现vue官网就给出了如何禁用prefetch的方法:vue官网对于prefetch介绍
这里又是一个坑,按照图上的配置过后发现没效果,难道官网也出错了?在vue.config.js中把config.plugins打印出来。
发现加载的插件没有prefetch,只有prefetch-index,prefetch后面的-xxx是和page里面配置名称是有关系的。
//vue.config.js
module.exports = {
pages: {
//和这个配置有关
index: {
...
},
},
}
更改移除的插件名称并运行项目
//vue.config.js
module.exports={
chainWebpack: (config) => {
// 移除 prefetch 插件
config.plugins.delete('prefetch-index')
},
}
可以看到只加载了首页的需要的路由,实现了懒加载,在网络不好的情况下进一步提升首屏速度。
写在最后
转载自:https://juejin.cn/post/7234763686475366459