出处:掘金
原作者:金泽宸
性能优化不是“事后修补”,而是系统架构中每一个决策点的结果
写在前面
“页面很卡”、“首屏很慢”、“加载太久”、“滚动掉帧”——这些都是前端性能问题的常见表现
一个高级架构师不仅要能定位问题、给出方案、落地优化,更要具备系统性思维:把性能优化融入构建、路由、组件、渲染、交互、网络、缓存、部署等全链路
本篇我们将给出一张“性能优化地图”,并通过实战落地多个优化点,包括:
- 首屏优化
- 资源体积控制
- 图片懒加载 + 动态加载
- 虚拟滚动、节流防抖、分块渲染
- 网络优化 + HTTP 缓存 + CDN
- 性能指标监控接入
前端性能优化地图(全链路)
[构建层]
├─ Tree-shaking、按需加载、压缩、缓存拆包
[渲染层]
├─ SSR/CSR/SPA 混合渲染、虚拟列表、分片渲染
[交互层]
├─ 节流、防抖、懒加载、骨架屏
[网络层]
├─ CDN、缓存策略、预加载、并发控制
[运行层]
├─ lazy import、空闲加载、缓存池、service worker
[监控层]
└─ FCP、LCP、TTFB、FPS、Error 捕获
核心性能指标理解(建议纳入监控)
指标 | 含义 | 建议范围 |
---|---|---|
FCP | First Contentful Paint | < 1s |
LCP | Largest Contentful Paint | < 2.5s |
TTFB | Time to First Byte | < 0.5s |
TTI | Time to Interactive | < 3s |
FPS | 每秒帧数 | > 55fps |
CLS | 页面偏移稳定性 | < 0.1 |
构建阶段优化策略
代码体积减小
- Tree-shaking(去掉无用 import)
- 使用 ES Modules + import.meta.glob 动态按需加载
- 分包拆分 + lazy load:
const Page = defineAsyncComponent(() => import('./BigPage.vue'))
- UI 框架按需引入(如
unplugin-vue-components
)
静态资源优化
- 图片压缩(tinyjpg +
vite-plugin-imagemin
) - SVG icon 合并 + inline 渲染
- 使用 CDN 加载大体积库(如 echarts、lodash)
首屏加载优化策略
Skeleton 骨架屏
<Skeleton v-if="loading" />
<RealContent v-else />
异步组件拆分加载
const Home = defineAsyncComponent(() => import('./pages/Home.vue'))
预加载关键资源
<link rel="preload" href="/fonts/roboto.woff2" as="font" />
或使用 Vite 配置 rollupOptions.output.manualChunks
进行分包。
页面滚动与渲染优化
场景 1:表格/列表数据量大
使用虚拟滚动(如 vue-virtual-scroller
):
<VirtualList :item-count="list.length">
<template #default="{ index }">
{{ list[index].name }}
</template>
</VirtualList>
手动分页 + 分块渲染:
const chunkedData = list.slice(startIndex, endIndex)
交互层性能提升技巧
问题 | 优化方式 |
---|---|
快速滚动卡顿 | 使用 requestAnimationFrame 包装回调 |
持续输入抖动 | 使用 useDebounceFn / lodash.debounce |
多次点击触发请求 | 使用 throttle 控制频率 |
动画卡顿 | 使用 transform + will-change 减少 reflow |
网络请求与缓存优化
技术建议:
- 合理设置 HTTP 缓存头(
cache-control
,ETag
) - 静态资源使用 CDN
- 使用服务端压缩(gzip、brotli)
- 并发控制(Axios 请求队列 / 限流器)
数据缓存建议:
- 前端接口缓存(如使用
swr
,react-query
,vue-query
) localStorage
缓存接口数据 + 版本号判断- 长期数据缓存建议使用 IndexedDB(如大图/富媒体/文件列表)
运行时延迟加载机制
- 空闲时加载重资源:
requestIdleCallback(() => import('./heavy.js'))
- 多标签页面延迟加载非当前 Tab 组件内容:
<TabPane v-if="active === 'b'" />
- 按需加载非关键图标、图表、地图组件
接入性能监控与分析工具
接入推荐:
- Web-vitals(Google 官方推荐)
- Sentry Performance
- Vite Plugin Visualizer(打包体积分析)
- Lighthouse 自动分析
import { getLCP, getFID, getCLS } from 'web-vitals'
getLCP(console.log)
getFID(console.log)
getCLS(console.log)
团队层面优化建议
目标 | 建议 |
---|---|
发现性能问题 | 接入 web-vitals / Sentry trace 分析 |
控制代码体积 | 配置体积阈值报警,使用 visualizer 检查大模块 |
组件规范 | 所有组件必须支持懒加载、分页、lazy 渲染 |
提效流程 | 接入自动构建时间、首屏测速、部署前分析报告 |
性能 review | PR 检查 checklist 中加入“性能影响项” |