Vue3项目构建与首屏性能优化工程方案
Vue3 + Vite项目在业务迭代中,随着依赖包和组件数量增长,开发环境启动变慢、生产构建时间拉长、首屏加载超过3秒的问题日益突出。本文记录一个中等规模Vue3项目(120+组件、40+路由)从首屏3.2秒优化到800毫秒的完整过程。
构建产物分析:找出体积瓶颈
优化前先量化。安装rollup-plugin-visualizer生成构建产物分析图:
npm install -D rollup-plugin-visualizer
// vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
vue(),
visualizer({ open: true, gzipSize: true, brotliSize: true })
]
})
构建后打开stats.html,发现三个主要问题:Element Plus未按需引入导致整体包1.8MB;Lodash全量引入占230KB;ECharts未拆包占890KB。
依赖包按需引入与Tree Shaking
Element Plus按需引入
使用unplugin-vue-components和unplugin-auto-import自动按需导入:
npm install -D unplugin-vue-components unplugin-auto-import
// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
AutoImport({ resolvers: [ElementPlusResolver()] }),
Components({ resolvers: [ElementPlusResolver()] })
]
})
此改动将Element Plus的产物体积从1.8MB降至320KB。
Lodash替换
将全量引入import _ from 'lodash'替换为按需import debounce from 'lodash/debounce'。或使用lodash-es支持Tree Shaking:
import { debounce, throttle } from 'lodash-es'
Lodash体积从230KB降至12KB。
ECharts动态加载与异步组件拆分
ECharts是最大的单包依赖。通过动态import实现按路由加载:
// charts.ts
export async function useECharts() {
const echarts = await import('echarts/core')
const { BarChart, LineChart } = await import('echarts/charts')
const { GridComponent, TooltipComponent } = await import('echarts/components')
const { CanvasRenderer } = await import('echarts/renderers')
echarts.use([BarChart, LineChart, GridComponent, TooltipComponent, CanvasRenderer])
return echarts
}
在路由配置中使用Vue3的异步组件加载图表页面:
const routes = [
{
path: '/dashboard',
component: () => import('@/views/Dashboard.vue') // 图表组件在路由切换时才加载
}
]
ECharts从首屏主包移出,首屏JS体积减少890KB。
Vite构建配置深度调优
手动Chunk拆分
将稳定的大依赖拆为独立chunk,利用浏览器长期缓存:
// vite.config.ts
build: {
rollupOptions: {
output: {
manualChunks: {
'vendor-vue': ['vue', 'vue-router', 'pinia'],
'vendor-ui': ['element-plus'],
'vendor-echarts': ['echarts/core', 'echarts/charts', 'echarts/renderers']
}
}
}
}
CSS代码拆分
开启CSS代码拆分,避免首屏加载全站样式:
build: {
cssCodeSplit: true // Vite默认为true,确认未被覆盖为false
}
生产环境去除Source Map
build: {
sourcemap: false,
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
}
资源预加载与缓存策略
对关键路由实施prefetch,利用浏览器空闲时间加载:
<link rel="prefetch" href="/assets/vendor-vue.[hash].js">
<link rel="prefetch" href="/assets/vendor-ui.[hash].js">
Nginx侧对静态资源设置长期缓存头:
location /assets/ {
expires 365d;
add_header Cache-Control "public, immutable";
gzip on;
gzip_types application/javascript text/css;
gzip_min_length 1024;
}
开启Brotli压缩后,vendor-vue chunk从234KB压缩至68KB,传输体积进一步缩小。
优化效果量化对比
优化前后关键指标对比(基于Lighthouse 6次采集中位数):
首屏FCP:3.2s → 0.8s
首屏LCP:4.1s → 1.2s
JS总传输体积:3.8MB → 1.1MB
构建时间:48s → 29s
请求数:67 → 38
核心手段归纳:按需引入消灭无用代码,动态import延迟非首屏依赖,手动chunk利用浏览器缓存,压缩与预加载缩短网络传输时间。这些手段组合使用,对中等规模Vue3项目的性能提升效果显著。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/vue3-xiang-mu-vite-gou-jian-xing-neng-you-hua-cong-shou/