说明:标题提到的Vite 4.0在本文写作时(2022年11月14日)尚未正式发布(Vite 4.0于12月发布),本文主要基于Vite 3.0的实战经验,并展望Vite 4.0的改进。
Vite是新一代前端构建工具,以快著称。但项目大了之后,Vite也会变慢。本文分享Vite项目的性能优化实战,包括开发环境优化、构建优化、运行时优化,以及常见问题和解决方案。
一、Vite为什么快
在说优化之前,先说说Vite为什么快。
1. 原生ESM
Vite利用浏览器原生的ES模块,开发时不需要打包。
- 传统工具(Webpack):开发时要把所有模块打包成一个bundle,项目大了就慢
- Vite:开发时直接用浏览器的ESM,按需编译,启动快
2. 按需编译
Vite只编译浏览器请求的模块。
- 你访问哪个页面,就编译哪个页面的模块
- 没访问的模块,不编译
- 项目越大,优势越明显
3. 预构建
Vite用esbuild预构建依赖。
- esbuild用Go写的,比JavaScript快10-100倍
- 预构建第三方依赖,转换成ESM
- 缓存预构建结果,下次启动更快
4. HMR
Vite的热更新(HMR)很快。
- 只更新修改的模块
- 不重新打包整个应用
- 状态保持,刷新快
二、开发环境优化
开发环境的优化,主要是提升启动速度和HMR速度。
1. 依赖预构建优化
Vite会预构建依赖,但可以手动配置。
// vite.config.js
export default {
optimizeDeps: {
// 强制预构建这些依赖
include: ['lodash', 'moment'],
// 排除这些依赖(不要预构建)
exclude: ['some-esm-package'],
}
}优化点:
- 把常用的依赖加入include,避免运行时再编译
- 把已经是ESM的依赖加入exclude,避免重复转换
- 预构建结果会缓存,第一次慢,后面快
2. 减少入口文件
入口文件太多,会影响启动速度。
- 尽量用一个入口
- 多页应用,合理配置rollupOptions.input
- 不要在入口文件里导入太多东西
3. 关闭不必要的功能
开发时,可以关闭一些不必要的功能。
export default {
server: {
// 关闭sourcemap(如果不需要)
sourcemap: false,
}
}注意:sourcemap对调试很重要,除非确实不需要,否则不要关。
4. 用更快的依赖
有些依赖比较大或比较慢,可以替换。
- 用dayjs代替moment(小很多)
- 用lodash-es代替lodash(支持tree shaking)
- 按需导入,不要全量导入
// 不好
import _ from 'lodash'
// 好
import { debounce } from 'lodash-es'5. 合理配置别名
别名可以简化导入,但不要太多。
export default {
resolve: {
alias: {
'@': '/src',
'@components': '/src/components',
}
}
}别名太多,会影响解析速度。保持简洁。
三、构建优化
构建优化,主要是提升构建速度和减小产物体积。
1. 代码分割
合理配置代码分割,减小首屏体积。
export default {
build: {
rollupOptions: {
output: {
manualChunks: {
// 把第三方库单独打包
vendor: ['vue', 'vue-router', 'pinia'],
// UI库单独打包
ui: ['element-plus'],
// 工具库单独打包
utils: ['lodash-es', 'dayjs'],
}
}
}
}
}注意:
- 不要过度分割,太多小文件反而慢
- 合理分组,把不常变的放在一起
- 用分析工具看效果
2. 压缩优化
Vite默认用esbuild压缩,也可以用terser。
export default {
build: {
// 用terser压缩(比esbuild压缩率高,但慢)
minify: 'terser',
terserOptions: {
compress: {
// 移除console
drop_console: true,
// 移除debugger
drop_debugger: true,
}
}
}
}选择:
- 追求构建速度:用esbuild(默认)
- 追求产物体积:用terser
3. 图片优化
图片是产物体积的大头。
- 用现代格式(WebP、AVIF)
- 压缩图片
- 懒加载
- 用CDN
Vite插件:
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
export default {
plugins: [
ViteImageOptimizer({
png: { quality: 80 },
jpeg: { quality: 80 },
webp: { quality: 80 },
})
]
}4. 按需导入
按需导入,减小产物体积。
- UI库:用按需导入插件
- 工具库:只导入需要的函数
- 图标:只导入用到的图标
// 不好
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 好
import { ElButton, ElInput } from 'element-plus'5. 外部化依赖
如果用CDN,可以把依赖外部化。
export default {
build: {
rollupOptions: {
external: ['vue', 'vue-router'],
}
}
}注意:外部化需要在HTML里用CDN引入,适合有CDN的项目。
四、运行时优化
构建产物小了,运行时也要优化。
1. 路由懒加载
路由懒加载,只加载当前页面的代码。
const router = createRouter({
routes: [
{
path: '/home',
component: () => import('./views/Home.vue')
},
{
path: '/about',
component: () => import('./views/About.vue')
}
]
})2. 组件懒加载
大组件也可以懒加载。
<script setup>
import { defineAsyncComponent } from 'vue'
const BigChart = defineAsyncComponent(() => import('./BigChart.vue'))
</script>
<template>
<BigChart v-if="showChart" />
</template>3. 虚拟列表
长列表用虚拟列表,只渲染可见区域。
- 用vue-virtual-scroller
- 或自己实现
- 大量数据时,性能提升明显
4. 防抖节流
频繁触发的事件,用防抖节流。
import { debounce, throttle } from 'lodash-es'
// 防抖:搜索输入
const onSearch = debounce((value) => {
// 搜索逻辑
}, 300)
// 节流:滚动事件
const onScroll = throttle(() => {
// 滚动逻辑
}, 100)5. 避免不必要的渲染
- 用v-show代替v-if(频繁切换时)
- 用computed缓存计算结果
- 合理使用watch,不要过度监听
- 大列表用key,且key稳定
五、分析工具
优化之前,先分析,找到瓶颈。
1. rollup-plugin-visualizer
分析产物体积。
import { visualizer } from 'rollup-plugin-visualizer'
export default {
plugins: [
visualizer({
open: true,
filename: 'stats.html',
})
]
}运行构建后,会打开一个可视化页面,看到每个模块的体积。
2. Vite的debug模式
看Vite的详细日志。
vite --debug可以看到:
- 预构建了哪些依赖
- 每个请求的耗时
- HMR的耗时
3. 浏览器开发者工具
用浏览器的Performance面板分析运行时性能。
- 看加载时间
- 看渲染时间
- 看脚本执行时间
- 找到瓶颈
六、常见问题
1. 启动慢
可能的原因:
- 依赖太多,预构建慢
- 入口文件太大
- 别名太多
- 插件太多
解决方案:
- 优化依赖预构建
- 减少入口
- 精简别名和插件
- 用更快的依赖
2. HMR慢
可能的原因:
- 修改的文件影响范围大
- 组件太大
- 样式文件太多
- 插件影响HMR
解决方案:
- 拆分大组件
- 合理组织代码
- 检查插件是否影响HMR
- 用Vite的debug模式看耗时
3. 构建慢
可能的原因:
- 项目太大
- 用了terser压缩
- 图片太多太大
- 插件太多
解决方案:
- 用esbuild压缩(默认)
- 优化图片
- 精简插件
- 升级硬件或用CI构建
4. 产物体积大
可能的原因:
- 全量导入依赖
- 图片没压缩
- 没有代码分割
- 没有按需导入
解决方案:
- 按需导入
- 压缩图片
- 代码分割
- 外部化依赖
七、Vite 4.0展望
Vite 4.0预计2022年12月发布,主要改进:
1. Rollup 3
Vite 4.0升级到Rollup 3。
- 构建更快
- 更好的tree shaking
- 更好的代码分割
- 修复了一些bug
2. 更快的冷启动
Vite 4.0优化了冷启动。
- 更快的依赖扫描
- 更好的缓存策略
- 减少不必要的工作
3. 更好的HMR
HMR更稳定、更快。
- 修复了一些HMR的bug
- 更好的CSS HMR
- 更快的更新
4. 其他改进
- 更好的SSR支持
- 更好的环境变量处理
- 更多的配置选项
- 文档改进
建议:Vite 4.0发布后,可以升级体验。
八、优化实战案例
分享一个我做过的优化案例。
项目情况:
- 中后台系统,Vue 3 + Vite 3
- 50多个页面,200多个组件
- 启动时间:15秒
- 构建时间:3分钟
- 首屏体积:2MB
优化措施:
- 依赖预构建:把常用依赖加入include
- 按需导入:Element Plus按需导入
- 代码分割:按路由和依赖分组
- 图片优化:压缩图片,用WebP
- 路由懒加载:所有路由懒加载
- 大组件懒加载:图表组件懒加载
- 用esbuild压缩
优化结果:
- 启动时间:15秒 → 5秒
- 构建时间:3分钟 → 1分钟
- 首屏体积:2MB → 500KB
- 用户体验明显提升
九、写在最后
Vite很快,但项目大了也需要优化。
优化的思路:
- 先分析,找到瓶颈
- 开发环境:优化启动和HMR
- 构建:优化速度和产物体积
- 运行时:优化加载和渲染
- 持续优化,不要一劳永逸
Vite 4.0即将发布,会带来更多改进。但不管工具怎么变,优化的思路是一样的:找到瓶颈,对症下药。
最后,用一句话总结:"Vite很快,但优化无止境。分析瓶颈,对症下药,让你的项目从慢到快。"
愿你的Vite项目,又快又稳。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录