Vue3 性能优化实战:从 10s 到 1s 的加载速度提升

前言

在负责新能源场站智慧管理系统项目时,我们遇到了一个严峻的挑战:随着业务模块不断增加,系统首页加载时间从最初的 2s 飙升到 10s+,用户流失率高达 40%。

经过两周的性能优化攻坚,我们成功将首屏加载时间压缩到 1s 以内,LCP(最大内容绘制)从 8.5s 降至 0.9s,用户留存率提升 35%。

本文将分享我们在 Vue3 项目中实践的性能优化方案,涵盖代码分割、懒加载、构建优化、运行时优化四个维度,希望能给遇到类似问题的同学一些参考。


一、性能问题分析

1.1 现状数据

优化前的性能指标(Chrome DevTools Lighthouse):

指标 数值 评级
FCP (首屏内容绘制) 6.2s ❌ 差
LCP (最大内容绘制) 8.5s ❌ 差
TTI (可交互时间) 10.3s ❌ 差
总包体积 4.8MB ❌ 差
首屏请求数 45 ❌ 差

1.2 问题定位

使用 Webpack Bundle Analyzer 分析打包体积:

复制代码
npm install --save-dev webpack-bundle-analyzer
复制代码
// vite.config.js
import { visualizer } from 'rollup-plugin-visualizer'
​
export default {
  plugins: [
    visualizer({
      open: true,
      gzipSize: true,
      brotliSize: true,
    }),
  ],
}

发现问题

  1. ECharts 完整包 2.1MB,占总体积 44%

  2. 组件库全量引入 850KB

  3. 业务组件未做代码分割

  4. 图片资源未压缩


二、优化方案

2.1 路由懒加载 + 组件异步加载

优化前:所有路由组件同步加载

复制代码
// router/index.js - ❌ 不推荐
import Home from '@/views/Home.vue'
import Dashboard from '@/views/Dashboard.vue'
​
const routes = [
  { path: '/', component: Home },
  { path: '/dashboard', component: Dashboard },
]

优化后:路由级别代码分割

复制代码
// router/index.js - ✅ 推荐
const routes = [
  {
    path: '/',
    component: () => import('@/views/Home.vue'),
  },
  {
    path: '/dashboard',
    component: () => import('@/views/Dashboard.vue'),
  },
]

效果:首屏 JS 体积减少 65%,从 2.8MB 降至 980KB

2.2 第三方库按需引入

ECharts 按需加载

优化前

复制代码
// ❌ 全量引入 2.1MB
import * as echarts from 'echarts'

优化后

复制代码
// ✅ 按需引入,体积减少 80%
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { BarChart, LineChart, PieChart } from 'echarts/charts'
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
} from 'echarts/components'
​
use([
  CanvasRenderer,
  BarChart,
  LineChart,
  PieChart,
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
])
Element Plus 按需自动导入
复制代码
npm install -D unplugin-vue-components unplugin-auto-import
复制代码
// vite.config.js
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
​
export default {
  plugins: [
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
}

效果:组件库体积从 850KB 降至 180KB

2.3 虚拟列表优化长列表渲染

场景:场站设备列表 5000+ 条数据

优化前

复制代码
<template>
  <div class="device-list">
    <div v-for="device in devices" :key="device.id" class="device-item">
      {{ device.name }} - {{ device.status }}
    </div>
  </div>
</template>
​
<script setup>
const devices = ref([...5000 条数据])
</script>

优化后 :使用 vue-virtual-scroller

复制代码
npm install vue-virtual-scroller
复制代码
<template>
  <RecycleScroller
    class="device-list"
    :items="devices"
    :item-size="60"
    key-field="id"
  >
    <template #default="{ item }">
      <div class="device-item">
        {{ item.name }} - {{ item.status }}
      </div>
    </template>
  </RecycleScroller>
</template>

效果:DOM 节点从 5000+ 降至 20 个,渲染时间从 3.2s 降至 80ms

2.4 图片资源优化

WebP 格式转换
复制代码
# 使用 imagemin 批量转换
npm install -D vite-plugin-imagemin
复制代码
// vite.config.js
import viteImagemin from 'vite-plugin-imagemin'
​
export default {
  plugins: [
    viteImagemin({
      webp: { quality: 80 },
    }),
  ],
}
图片懒加载
复制代码
<template>
  <img v-lazy="device.image" :alt="device.name" />
</template>
​
<script setup>
import { Lazyload } from 'vue-lazyload'
​
app.use(Lazyload, {
  loading: '/loading.gif',
  error: '/error.png',
})
</script>

效果:图片资源体积减少 60%,首屏图片加载时间从 4.5s 降至 1.8s

2.5 Gzip/Brotli 压缩

复制代码
npm install -D vite-plugin-compression
复制代码
// vite.config.js
import viteCompression from 'vite-plugin-compression'
​
export default {
  plugins: [
    viteCompression({
      algorithm: 'brotliCompress',
      ext: '.br',
    }),
  ],
}

Nginx 配置

复制代码
location / {
  gzip on;
  gzip_types text/plain application/javascript text/css application/json;
  gzip_min_length 1000;
  
  # Brotli
  brotli on;
  brotli_types text/plain application/javascript text/css application/json;
}

效果:传输体积减少 70%,从 4.8MB 降至 1.4MB


三、优化效果对比

3.1 性能指标提升

指标 优化前 优化后 提升幅度
FCP 6.2s 0.8s 87% ⬆️
LCP 8.5s 0.9s 89% ⬆️
TTI 10.3s 1.2s 88% ⬆️
总包体积 4.8MB 1.1MB 77% ⬇️
首屏请求数 45 12 73% ⬇️

3.2 Lighthouse 评分

  • 优化前:42 分

  • 优化后:96 分

3.3 业务指标提升

指标 优化前 优化后 变化
用户留存率 60% 95% +35%
页面跳出率 45% 18% -27%
平均停留时长 2.5min 6.8min +172%

四、优化清单总结

✅ 构建时优化

  • 路由懒加载
  • 组件异步加载
  • 第三方库按需引入
  • Tree Shaking
  • Gzip/Brotli 压缩
  • 图片资源压缩

✅ 运行时优化

  • 虚拟列表
  • 图片懒加载
  • 防抖节流
  • 请求缓存
  • 组件缓存(keep-alive)

✅ 监控与持续优化

  • 性能监控埋点
  • 错误监控上报
  • 定期 Lighthouse 审计

五、核心代码片段

5.1 性能监控埋点

复制代码
// utils/performance.js
export function reportWebVitals() {
  import('web-vitals').then(({ onFCP, onLCP, onCLS, onTTI }) => {
    onFCP(console.log)
    onLCP(console.log)
    onCLS(console.log)
    onTTI(console.log)
  })
}
​
// main.js
import { reportWebVitals } from '@/utils/performance'
reportWebVitals()

5.2 请求拦截优化

复制代码
// utils/request.js
import axios from 'axios'
​
const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000,
})
​
// 请求缓存
const cache = new Map()
​
request.interceptors.request.use((config) => {
  if (config.cache) {
    const cached = cache.get(config.url)
    if (cached) {
      return cached
    }
  }
  return config
})
​
export default request

六、总结

性能优化是一个持续迭代的过程,需要根据实际业务场景选择合适的方案。本次优化的核心思路:

  1. 减少体积:代码分割、按需引入、压缩

  2. 减少请求:缓存策略、资源合并

  3. 优化渲染:虚拟列表、懒加载

  4. 持续监控:埋点统计、定期审计

核心指标:首屏加载 < 1s,LCP < 2.5s,TTI < 3s

希望本文能对你有所帮助!如有疑问,欢迎在评论区交流~


参考资料

  1. Vue3 官方文档 - 性能优化

  2. Vite 构建优化指南

  3. Web Vitals 性能指标

  4. ECharts 按需使用

如果觉得有帮助,欢迎点赞 👍 + 收藏 ⭐ + 关注,后续会分享更多前端实战经验!

相关推荐
小陈工2 小时前
Python Web开发入门(三):配置文件管理与环境变量最佳实践
开发语言·jvm·数据库·python·oracle·性能优化·开源
Mike117.20 小时前
GBase 8c 索引设计与性能优化实战
性能优化
终端鹿20 小时前
Vue3 高频面试题系列:响应式原理 / 组合式 API / 性能优化 3 大核心模块
性能优化
ofoxcoding1 天前
React 性能优化实战:我把一个卡成 PPT 的页面优化到丝滑的全过程
javascript·react.js·ai·性能优化
动恰客流管家1 天前
动恰3DV3丨 数据修正,破解客流失真断层,精准还原真实客流
大数据·人工智能·3d·性能优化
当时只道寻常1 天前
JavaScript 实现图片懒加载
javascript·性能优化
wang09071 天前
Linux性能优化之上下文切换
linux·运维·性能优化
UTwelve1 天前
【UE】如何正确旋转法线贴图
性能优化·ue5·材质·贴图·着色器
桌面运维家1 天前
Windows性能优化:任务管理器深度使用指南
windows·性能优化