1.发现的问题
线上项目加载缓慢,还存在切换路由无响应的情况。发现首页产生1000+请求量,于是着手开始优化。
项目build后的文件过大,系统首页产生过多的请求响应迟缓,严重影响体验。
搜索相关资料了解项目打包时可开启gzip静态资源压缩、公共代码抽离、CDN引入等方式,减少项目体积、减少不必要的资源加载。本文讲述纯前端优化不涉及后端,先上效果图
2.效果
优化前:
优化后:
项目体积从200M变为13M,首页请求数量从从千位数降为两位数!
3.开始优化
1、将 productionSourceMap 设为 false
在vue.config.js中module.exports写入:
module.exports = {
// ...
productionSourceMap: false,
}
2、关闭prefetch预加载
perfetch 用来告诉浏览器在页面加载完成后,利用空闲时间提前获取用户未来可能会访问的内容。实际发现这是首页产生1000+个请求的罪魁祸首,索性关闭预加载机制。
(1) 在vue.config.js中module.exports写入:
module.exports = {
// ...
chainWebpack: config => {
// 移除 prefetch 插件
config.plugins.delete('prefetch')
// 移除 preload 插件
config.plugins.delete('preload')
}
// ...
}
3、vue打包开启Gzip压缩及公共代码抽离
(1) 安装依赖:cnpm install --save-dev compression-webpack-plugin,我本机环境安装最新版本会打包报错,我选择降安装低版本。
(2) 在vue.config.js 顶部引入依赖
// 是否为生产环境
const isProduction = process.env.NODE_ENV !== 'development'
const CompressionWebpackPlugin = require('compression-webpack-plugin')
configureWebpack: config => {
// ...
if (isProduction) { //自定义环境变量
// gzip压缩
const productionGzipExtensions = ['html', 'js', 'css']
config.plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' + productionGzipExtensions.join('|') + ')$'
),
threshold: 10240, // 只有大小大于10240(10k)的资源会被处理
minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
deleteOriginalAssets: true // 删除原文件
})
)
// 公共代码抽离
config.optimization = {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'all',
test: /node_modules/,
name: 'vendor',
minChunks: 1,
maxInitialRequests: 5,
minSize: 0,
priority: 100
},
common: {
chunks: 'all',
test: /[\\/]src[\\/]js[\\/]/,
name: 'common',
minChunks: 2,
maxInitialRequests: 5,
minSize: 0,
priority: 60
},
styles: {
name: 'styles',
test: /\.(sa|sc|c)ss$/,
chunks: 'all',
enforce: true
},
runtimeChunk: {
name: 'manifest'
}
}
}
}
}
//...
}
(3)打包会生成.gz结尾的压缩文件,对应的nginx需要安装gzip static静态模块并开启gzip功能(可参考使用gzip优化页面加载遇到的问题)。
4、CDN引入
将引用的外部js、css文件剥离开来,不编译到vendor.js中,而是用资源的形式引用,这样浏览器可以使用多个线程异步将vendor.js、外部的js等加载下来,达到加速首页展示效果。
(1) 在vue.config.js 加入配置
// 是否为生产环境
// ...
const isProduction = process.env.NODE_ENV !== 'development'
const externals = {
// 属性名称 vue, 表示遇到 import xxx from 'vue' 这类引入 'vue'的,不去 node_modules 中找,而是去找全局变量 Vue(其他的为VueRouter、Vuex、axios、ELEMENT,注意全局变量是一个确定的值,不能修改为其他值,修改为其他大小写或者其他值会报错)
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex',
axios: 'axios'
}
const cdn = {
css: [],
js: [
//这里CDN地址推荐使用公司私有地址,外部CDN具有很大的不确定性
'https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.min.js',
'https://cdn.bootcdn.net/ajax/libs/vue-router/3.0.2/vue-router.min.js',
'https://cdn.bootcdn.net/ajax/libs/vuex/3.1.0/vuex.min.js',
'https://cdn.bootcdn.net/ajax/libs/axios/0.18.1/axios.min.js'
]
}
// ...
module.exports = {
// ...
chainWebpack: config => {
if (isProduction) { // 生产环境才注入cdn
config.plugin('html').tap(args => {
args[0].cdn = cdn
return args
})
//视为一个外部库,而不将它打包进来
config.externals(externals)
}
}
// ...
}
(2) 在public/index.html文件配置
使用webpack中自带的插件 html插件进行配置,在index.html中增加判断,是否使用 CDN,htmlWebpackPlugin.options使用的是vue.config中的config.plugin(‘html’)的插件属性。
<% 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 src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
5、最后
看到过一些文章借助 image-webpack-loader 对项目中的图片进行有损压缩从而减小项目体积,有兴趣的小伙伴可以尝试下,当然对于项目优化肯定是不会只有这几个方面的,还有更多其它的优化方法各位也可以一起沟通交流。