这是工作多年来第一次对项目做过的性能优化,回顾整理下。
项目
一个后台管理系统,大约由40+页面组成,基于 vue-cli3
构建
未处理前
未做任何处理前,代码打包的结果如下:
可以看出:chunk-vendor
文件超过了 1.8M
,app
文件超过了 1.1M
。
项目中所有的第三方库都被打包到了 chunk-vendor
中,项目所有的页面,自定义组件都被打包到了 app
文件中
当访问项目的时候,能明显感觉到白屏。(这个项目还不大,要是项目再大一点,想过会更明显。。)
访问项目,利用 chrome 自带的 converge 工具,查看了下文件的使用率:
可以看到,文件未使用率竟然超过了 70%+!!
优化处理
主要从以下几个常规方面做处理:
- 组件按需加载
- 第三方库按需加载
- 资源压缩处理
组件按需加载
优化前:
这种组件引入的方式不是按需加载的,不知道当时是从什么项目里面 copy 过来的方法。。。
router 文件夹下包含这么三个文件:
- import_files.js
- router.js
- router_map.js
文件内的内容大致如下:
// import_files.js
// 这个文件夹就这一句
module.exports = file => require('@/views/' + file + '.vue').default
// router.js
import Vue from 'vue'
import Router from 'vue-router'
import {
routerMap
} from './router-map'
Vue.use(Router)
export const constantRoutes = [{
path: '/login',
name: 'login',
hidden: true,
meta: {
title: '登录',
icon: ''
},
component: routerMap['login']
}
]
const createRouter = () => new Router({
mode: 'hash',
base: process.env.BASE_URL,
routes: constantRoutes
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
// 重置路由
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router
// router_map.js
const _importFile = require('./import_file')
export const routerMap = {
...,
error404: _importFile('Error/404'),
...
}
优化
- 去掉
import_files.js
文件 - 修改
router_map.js
文件
// router_map.js
export const routerMap = {
...,
layout: () => import('@/views/Layout/index.vue'),
...
}
打包效果:之前的一个文件被拆分成了多个文件,文件大小明显减小
chunk-vendor
文件从1.8M
减小到了900k
app.js
文件从1.1M
减小到了210k
这样打包有个问题:我们拆分粒度太细,每个页面都单独打包,打包出来的文件过多(优化前:2个js文件,2个css文件,优化后:40+js文件,40+css文件,并且最大的文件上百k,最小的零点几k
),造成请求过多
路由再次优化
路由分组加载:
修改 router_map.js
文件
// router_map.js
// 注意 import 中的注释!
// webpackChunkName 相同的页面会被打包到同个文件中
// 打包后的文件文件名中会有 webpackChunkName
export const routerMap = {
...,
layout: () => import(/* webpackChunkName: "group-order" */'@/views/Layout/index.vue'),
...
}
效果:
优化后:20+js文件,20+css文件,(由于文件过多,没有全部分组,全部分好组,文件还会更少)
文件数量还能再优化!!
vue-cli3
会默认开启一个css分离插件 ExtractTextPlugin
每一个模块的css文件都会分离出来,加载20+的css文件,花费了不少的资源请求时间
我们可以在vue.config.js中关闭它
module.exports = {
css: {
// 是否使用css分离插件 ExtractTextPlugin
extract: false,
// 开启 CSS source maps?
sourceMap: false,
// css预设器配置项
loaderOptions: {},
// 启用 CSS modules for all css / pre-processor files.
modules: false
},
}
配置完后,打包出来的项目就没有 css 文件了
取而代之的是整合起来的一个js文件
加载文件数减少,但体积变大,最终体验下来速度没有太大差异
所以,是否要css拆分,需要测试分析
第三方库按需加载
以 element-ui 为例
通常,我们在 main.js
中这样全局引入:
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
现调整为:
// 在main.js中引入大部分页面使用到组件
// 在对应页面中 引入只有当前页面使用到的组件
import { Button } from 'element-ui';
Vue.use(Button);
安装插件:
npm install babel-plugin-component -D
修改 babel.config.js
文件
plugins: [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
打包后,chunk-vendors
文件明显大小减少:(由于项目页面较多,我只是把用到的组件在 main.js
中 都引入了,如果把一些组件在页面中去引入,体积会更小)
资源压缩处理
服务器开启 gzip 即可(具体配置自行百度)。
如果服务器未开启 gzip
,前端卡打包出压缩文件,然后服务器配置:gzip_static on
也可实现
前端安装插件:
npm i -D compression-webpack-plugin
配置 vue.config.js
const CompressionPlugin = require("compression-webpack-plugin")
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
return {
plugins: [
new CompressionPlugin({
test: /\.js$|\.html$|\.css/,
threshold: 10240,
deleteOriginalAssets: false
})
]
}
}
}
}
打包后会生成 .gz
后缀的压缩文件
可能项目没有足够大,效不是非常明显,但还是能感觉到有一定的提升
性能优化路还很长,需要慢慢摸索
抽空准备把博客后台管理优化一下,每次打开都要等好久。。
初次尝试性能调优,可能有测得不到位的地方,欢迎指出