Vite相关性能优化
分包策略
在生产环境下 Vite 完全利用 Rollup 进行构建,因此拆包也是基于 Rollup 来完成的
Vite 默认拆包策略
只不过Rollup专注于JS库的打包,对应用构建的能力还有待提升,Vite 正好是补足了 Rollup 应用构建的能力,在拆包能力这一块的扩展就是很好的体现
项目的基本结构:
.
├── public
│ ├── vite.svg
├── src
│ ├── routes
│ │ └── index.ts //路由配置
│ ├── views
│ │ ├── AboutView.vue // 懒加载路由页面
│ │ ├── HomeView.vue // 直接加载路由页面
│ │ ├── PhotoView.vue // 懒加载路由页面
│ │ ├── StudentView.vue // 懒加载路由页面
│ │ └── UserView.vue // 懒加载路由页面
│ ├── App.vue
│ └── main.ts
└── index.html
打包之后的产物:
.
├── assets
│ ├── AboutView-355cc1df.js // Async Chunk
│ ├── AboutView-786d9592.css // Async Chunk (CSS)
│ ├── index-c0c63fdb.js // Initial Chunk
│ ├── index-d1e7a483.css // Initial Chunk (CSS)
│ ├── StudentView-85c73246.js // Async Chunk
│ └── UserView-18eefd25.js // Async Chunk
├── index.html // 入口 HTML
└── vite.svg // 静态资源
这是没有任何配置的vite打包之后的产物,自动对懒加载的路由和与其对应的css进行的处理
自定义拆包策略
针对更细粒度的拆包,Vite
还是基于的Rollup
处理。
manualChunks
主要有两种配置的形式,可以配置为一个对象或者一个函数。
对象方式
build: {
...
rollupOptions: {
output: {
...
manualChunks:{
'vue-vendor': ['vue', 'vue-router']
}
}
}
}
在对象格式的配置中,key
代表 chunk 的名称,value
为一个字符串数组,每一项为第三方包的包名
vite v4.4.9 building for production...
✓ 34 modules transformed.
dist/index.html 0.54 kB │ gzip: 0.33 kB
dist/assets/AboutView-786d9592.css 0.04 kB │ gzip: 0.06 kB
dist/assets/index-d1e7a483.css 0.27 kB │ gzip: 0.17 kB
dist/assets/UserView-9010cdee.js 0.55 kB │ gzip: 0.35 kB
dist/assets/StudentView-eff7d69a.js 0.55 kB │ gzip: 0.35 kB
dist/assets/AboutView-74a57329.js 0.78 kB │ gzip: 0.43 kB
dist/assets/index-4fb9786f.js 5.87 kB │ gzip: 2.06 kB
dist/assets/vue-vendor-99c39a4b.js 210.95 kB │ gzip: 49.67 kB
✓ built in 553ms
可以看到之前很大的index.js
文件被拆分了出来。
函数方式
manualChunks(id) {
if (id.includes('node_modules/vue')) {
return 'vue';
}
if (id.includes('element-plus')) {
return 'element-plus';
}
if (id.includes('lodash-es')) {
return 'lodash';
}
}
不过需要注意的是,这种方式在Vite4并不安全,因为如element-plus
内vue-demi
也依赖了Vue
,这里单独拆分Vue
的话,导致循环依赖的错误问题。
一般情况下,建议还是使用对象方式
treeshaking
这个没什么可多说的,不需要额外进行配置。
但有一个条件,必须是 ES6 module
模块才行,而且我们自己在引入的时候,注意只需要引入具体的函数(对象),不要直接导入全对象
代码压缩
Vite
默认使用esbuild
进行代码压缩,速度快,如果要追求压缩效果。
minify:esbuild
也可以使用terser
,Vite
也默认集成了terser
,只是需要手动导入terser
插件
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
}
},
GZIP压缩
gzip
是一种使用非常普遍的压缩格式。使用 gzip
压缩可以大幅减小代码体积,提升网络性能。当然gzip
只是其中一种,brotliCompress
也是一样,一般简称br
服务器就可以直接帮我们处理,不过需要耗费服务器性能,所以,一般前端也可能直接把打包之后的文件进行压缩处理,直接使用插件即可vite-plugin-compression2,
import { compression } from 'vite-plugin-compression2'
......
plugins: [
......
compression({
//压缩算法,默认gzip
algorithm: 'brotliCompress',
//匹配文件
include: [/\.(js)$/, /\.(css)$/,],
//压缩超过此大小的文件,以字节为单位
// threshold: 10240,
//是否删除源文件,只保留压缩文件
// deleteOriginalAssets: true
}),
]
图片压缩
图片压缩肯定可以减少网络传输,不过需要看项目对图片清晰度的需求,一般情况下,如果美工能直接处理最好,或者我们也可以使用外部工具进行处理,甚至是网上就可以直接处理,比如:tinypng
如果前端处理的话,可以使用插件vite-plugin-imagemin
import viteImagemin from 'vite-plugin-imagemin'
......
plugins: [
......
viteImagemin({
gifsicle: {
optimizationLevel: 7,
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
mozjpeg: {
quality: 20,
},
pngquant: {
quality: [0.8, 0.9],
speed: 4,
},
svgo: {
plugins: [
{
name: 'removeViewBox',
},
{
name: 'removeEmptyAttrs',
active: false,
},
],
},
}),
]
产物构建分析
为了能可视化地感知到产物的体积情况,推荐大家用rollup-plugin-visualizer来进行产物分析
import { visualizer } from "rollup-plugin-visualizer";
......
plugins: [
visualizer({
// 是否打包完成之后直接打开
open: true,
}),
],
CDN加速
使用CDN,可以让用户从最近的服务器请求资源,能够大大的提高资源的请求获取的速度。特别是一些第三方资源库,放在CDN上不但可以提高资源请求速度,而且也能大大降低我们打包体积和打包速度。
如果要把项目中的一些第三方资源放入到CDN,但是项目中我们又使用了这些资源,需要在项目中进行处理。一般比较常用的处理方式是直接使用第三方插件。比如:rollup-plugin-external-globals
import externalGlobals from "rollup-plugin-external-globals";
......
rollupOptions: {
external:['vue','vue-router','element-plus','vue-echarts','echarts','@vueuse/core'],
plugins: [
externalGlobals({
"vue": "Vue",
"vue-router": "VueRouter",
"element-plus": 'ElementPlus',
"@vueuse/core": "VueUse",
"echarts": "echarts",
"vue-echarts": "VueECharts",
})
],
}
打包处理
如果希望设置打包之后的文件位置,可以通过相关rollup设置处理
build:{
rollupOptions: {
output: {
chunkFileNames: 'assets/[name]-[hash].js',
entryFileNames: 'assets/[name].[hash].js',
assetFileNames: 'assets/xxx/[ext]/[name]-[hash].[ext]',
}
}
自定义插件
Vite 插件扩展了设计出色的 Rollup 接口,整个Rollup插件结构体系比较庞杂,简单来说,分成了build
和output
两大工作流的不同阶段进行分类。这个还需要单独去学习。就Vite来说他有可以和rollup结合的通用钩子,也有自己的独有钩子
Vite独有钩子:
钩子名称 | 释义 |
---|---|
config | 在解析 Vite 配置前调用。钩子接收原始用户配置(命令行选项指定的会与配置文件合并)和一个描述配置环境的变量,包含正在使用的 mode 和 command。 |
configResolved | 在解析 Vite 配置后调用。使用这个钩子读取和存储最终解析的配置。 |
configureServer | 是用于配置开发服务器的钩子。 |
configurePreviewServer | 与 configureServer 相同但是作为预览服务器。 |
transformIndexHtml | 转换 index.html 的专用钩子。钩子接收当前的 HTML 字符串和转换上下文。 |
handleHotUpdate | 执行自定义 HMR 更新处理。 |