赞
踩
我接手vue2的一个旧项目,因为首屏加载很慢,要求我对此进行优化。我在此进行记录
推荐使用webpack-bundle-analyzer
插件,可以对打包后的文件大小进行可视化分析。简单好用
安装插件
npm install webpack-bundle-analyzer --save-dev
在vue.config.js
文件中添加对应配置
// 引入插件 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin module.exports = { publicPath: '/', lintOnSave: true, productionSourceMap: false, filenameHashing: true, configureWebpack: (config) => { const plugins = [] // 配置BundleAnalyzerPlugin plugins.push( new BundleAnalyzerPlugin({ analyzerMode: 'server', analyzerHost: '127.0.0.1', analyzerPort: 8888, // 运行后的端口号 reportFilename: 'report.html', defaultSizes: 'parsed', openAnalyzer: true, generateStatsFile: false, statsFilename: 'stats.json', statsOptions: null, logLevel: 'info', }) ) return { plugins } } }
配置完成后执行npm run build
则自动打开页面展示文件大小。如下图:
可以看到优化前node_modules
模块占据了整个页面的将近70%大小(页面中占据面积越大的,也就是打包后体积越大的),其中显眼的插件有tinymce
、xlsx
、avue.min.js
、theme.js
、swiper.js
、html2canvas.js
后面优化只要对症下药即可。优化掉对应的插件。网上提供的思路是使用cdn进行优化。下面进行详细记录
使用cdn优化即需要使用外链引入对应插件,那么就需要在index.html
文件中添加对应的引入链接。然后需要在打包的时候把通过外链引入的插件排除在外,不进行打包。这里推荐使用这个网站搜索你要的插件,进行CDN外链引入
https://www.jsdelivr.com/
index.html
引入外链
在index.html
文件中添加如下代码:
<!-- 使用CDN的CSS文件 -->
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
<% } %>
<!-- 使用CDN加速的JS文件,配置在vue.config.js下 -->
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
<script type="text/javascript" src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
配置不打包对应的插件
在vue.config.js
文件中添加以下配置
// 配置不打包的模块 const externals = { // 左边是引入的参数,例如 import Vue from 'vue' 这里面的 'vue' // 右边是CDN模块的导出对象字段 vue: 'Vue', 'vue-router': 'VueRouter', vuex: 'Vuex', axios: 'axios', '@smallwei/avue': 'AVUE', 'element-ui': 'ELEMENT', xlsx: 'XLSX', tinymce: 'tinymce', html2canvas: 'html2canvas', echarts: 'echarts', } // CDN外链,会插入到index.html中 const cdn = { // 开发环境 dev: { css: [], js: [], }, // 生产环境 build: { css: [], js: [ // cdn.jsdelivr.net域名下的cdn文件 'https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js', 'https://cdn.jsdelivr.net/npm/vue-router@3.1.3/dist/vue-router.min.js', 'https://cdn.jsdelivr.net/npm/vuex@3.2.0/dist/vuex.min.js', 'https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js', 'https://cdn.jsdelivr.net/npm/element-ui@2.15.6/lib/index.js', 'https://cdn.jsdelivr.net/npm/@smallwei/avue@2.6.18/lib/avue.min.js', 'https://cdn.jsdelivr.net/npm/xlsx@0.17.5/xlsx.js', 'https://cdn.jsdelivr.net/npm/tinymce@5.10.2/tinymce.min.js', 'https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.js', 'https://cdn.jsdelivr.net/npm/echarts@4.8.0/dist/echarts.min.js' ], }, } module.exports = { publicPath: publicPath, lintOnSave: true, productionSourceMap: false, filenameHashing: true, configureWebpack: (config) => { const plugins = [] // 配置BundleAnalyzerPlugin plugins.push( new BundleAnalyzerPlugin({ analyzerMode: 'server', analyzerHost: '127.0.0.1', analyzerPort: 8888, // 运行后的端口号 reportFilename: 'report.html', defaultSizes: 'parsed', openAnalyzer: true, generateStatsFile: false, statsFilename: 'stats.json', statsOptions: null, logLevel: 'info', }) ) if (process.env.NODE_ENV === 'production') { // externals里的模块不打包 config.externals = externals } return { plugins } }, chainWebpack: (config) => { // 添加自定义参数cdn config.plugin('html').tap((args) => { if (process.env.NODE_ENV === 'production') { args[0].cdn = cdn.build } else { args[0].cdn = cdn.dev } return args }) }, }
完成以上配置后,再运行npm run build
得出以下结果:
可以看到优化前node_modules
模块打包后占了12.48M,优化后nodee_modules
模块打包后占了4.02M。
首屏加载的时间从原来的5s变成了3s,还有很多插件也可以使用cdn进行优化,只需要将上图占面积大的插件进行优化即可。另外,由于老项目,经手了很多人,太多重复性代码,所以上图左边views
模块占了很大空间。漫漫优化路,无穷无尽。
/-------------------------------------------------------------- 分割线 ------------------------------------------------------------------------/
按照上面的优化思路实现后发现还是不够快,需要更进一步优化。分析其原因,发现在加载首页的时候将打包后的所有的js文件,css文件都引入了。这就会导致花费了大量时间加载不必要的文件。欸,没错。这时就需要使用路由懒加载进行拆分,只加载当前页面需要的js和css文件,减少不必要的文件请求。
网上可以查到多种不同的懒加载方式,这里使用官方介绍的把组件按组分块来进行路由懒加载
const UserDashboard = () => import(/* webpackChunkName: "group-user" */ './UserDashboard.vue')
配置不同的webpackChunkName
就可以将对应的组件打包进对应文件中,轻松实现分块打包。
原以为这就结束了,但是打包后一看index.html
文件,发现事情不简单
打包确实分块了,但是入口文件还是将所有的js和css文件都引入了,这是为什么?
原因是vue-cli3 默认会把所有通过import()按需加载的javascript文件加上 prefetch,也就是上图中link
标签后面的属性rel=prefetch
prefetch链接会消耗宽带,因此我们要将prefetch
手动关掉,使入口文件只有必要的js和css文件。
关闭prefetch
代码如下:
// vue.config.js
module.exports = {
chainWebpack: config => {
// 移除 prefetch 插件
config.plugins.delete('prefetch')
// 或者
// 修改它的选项:
config.plugin('prefetch').tap(options => {
options[0].fileBlacklist = options[0].fileBlacklist || []
options[0].fileBlacklist.push(/myasyncRoute(.)+?\.js$/)
return options
})
}
}
再进行打包,观察入口文件结果如下:
完美!至此完成路由懒加载~
这一块不用多说,像ElementUI
、echarts
等等,体积较大的插件,如果只用到其中的几个模块但全局引入了,会导致文件过大。
echarts
的按需引入直接参照官网即可:
https://echarts.apache.org/handbook/zh/basics/import
elementUI
的按需引入过程中,配置中会存在一点小问题。
如果脚手架比较新没有 .babelrc
文件,则修改babel.config.js
文件,添加配置项:
{
"presets": [["es2015", { "modules": false }]], //如果配置后报错,把这里的数组项改成右边的即可 ["@babel/preset-env", { "modules": false }]
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
还有一个小问题就是element的隐藏组件scrollBar并没有对外暴露,这个组件无法按需引入。
至此首页快了非常多,观察首页的所有请求,发现还有两张图片请求较大,便将图片进行压缩(原来的我以为图片压缩会导致像素变低,直到我在网上尝试了压缩图片,压缩前后的观感完全一样,但是文件大小直接降低了近70%。不过大部分压缩图片的网站是需要会员或者收费的)
下面是我常用的一个免费的压缩图片的网站:
https://kt.fkw.com/yasuo.html?_ta=8780
压缩完图片进行替换,请求再次变小,速度再次提升。
最后如果服务器有nginx
代理的话,可以配置gzip
压缩传输,速度会更快,但是这里服务器没有使用nginx
代理,故不能配置gzip
了,不然我想这个网站肯定可以更快
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。