一、性能指标体系
核心网页指标(Core Web Vitals)
| 指标 | 全称 | 含义 | 目标值 |
|---|---|---|---|
| LCP | Largest Contentful Paint | 最大内容绘制 | < 2.5s |
| INP | Interaction to Next Paint | 交互到下次绘制 | < 200ms |
| CLS | Cumulative Layout Shift | 累计布局偏移 | < 0.1 |
其他重要指标
- FCP(First Contentful Paint):首次内容绘制,< 1.8s 为良
- TTFB(Time To First Byte):首字节时间,< 800ms 为良
- TTI(Time To Interactive):可交互时间,越短越好
- TBT(Total Blocking Time):总阻塞时间,< 200ms 为良
测量工具
- Lighthouse(Chrome DevTools / CI 集成)
- WebPageTest(真实网络多地测试)
- Chrome DevTools Performance(运行时分析)
- PerformanceObserver API(线上真实用户监控 / RUM)
二、网络传输优化
1. 减少 HTTP 请求数
- 合并 CSS/JS 文件(构建工具自动处理)
- 使用 CSS Sprite 或 SVG Symbol 合并图标
- 内联关键 CSS(Critical CSS)
- HTTP/2 多路复用下适度拆包(避免过大 bundle)
2. 减小传输体积
- Gzip / Brotli 压缩 :文本资源(HTML/CSS/JS)压缩率 70%+ ,Nginx 配置
gzip on; brotli on; - JS Tree Shaking:移除未使用代码,Rollup/Vite 默认开启
- 代码压缩 Minify:Terser(JS)、cssnano(CSS)
- 图片优化 :
- 使用现代格式:WebP(比 JPEG 小 25-35%)、AVIF(更小)
- 合理压缩:imagemin、sharp
- 响应式图片:
<img srcset>按屏幕分辨率加载合适尺寸 - SVG 替代位图(图标/简单图形)
3. 缓存策略
# HTML 入口文件 - 每次验证(保证拿最新)
Cache-Control: no-cache
# 带 hash 指纹的静态资源 - 长期强缓存
Cache-Control: max-age=31536000, immutable
# API 接口 - 按业务决定
Cache-Control: no-store # 或 max-age=60
- Service Worker 缓存:离线可用,精细控制缓存策略
- CDN 缓存:静态资源分发到用户最近节点
4. 减少 DNS 查询 / 连接建立时间
<!-- DNS 预解析 -->
<link rel="dns-prefetch" href="//api.example.com">
<!-- 提前建立 TLS 连接 -->
<link rel="preconnect" href="https://cdn.example.com" crossorigin>
5. 资源预加载
<!-- 关键资源提前加载(字体、首屏图、关键 CSS) -->
<link rel="preload" href="/fonts/main.woff2" as="font" crossorigin>
<link rel="preload" href="/hero.webp" as="image">
<!-- 预取下一页可能需要的资源 -->
<link rel="prefetch" href="/next-page.js">
三、JavaScript 优化
1. 代码分割(Code Splitting)
// 路由级分割 - React
const Dashboard = React.lazy(() => import('./Dashboard'));
// 条件加载
if (user.isPremier) {
const { PremierFeature } = await import('./PremierFeature');
}
- 入口分割:每个路由独立 chunk
- 动态导入:按需加载非首屏功能
- 第三方库分包:
vendor chunk单独分离,利用浏览器缓存
2. 减少主线程阻塞
-
长任务拆分 :将耗时任务拆为 <50ms 的小任务
// 使用 scheduler.yield() 或 setTimeout 让出主线程 for (const item of hugeList) { processItem(item); if (每处理N个) await scheduler.yield(); // 让浏览器响应交互 } -
Web Worker:CPU 密集型计算放后台线程(图像处理、数据加密)
-
避免不必要的 polyfill :
@babel/preset-env按 browserslist 精确 polyfill
3. 渲染性能优化
- 防抖(debounce) 处理输入、搜索事件
- 节流(throttle) 处理 scroll、resize 事件
- 虚拟列表(Virtual Scroll) :只渲染可视区域内的列表项(
react-virtual、vue-virtual-scroller) - 避免强制同步布局:读写 DOM 属性要分离,不要在循环中交替读写
4. 包体积分析
# Vite 项目
npx vite-bundle-analyzer
# webpack 项目
npx webpack-bundle-analyzer
- 检查是否有重复依赖
- 检查是否有体积过大的库(moment.js → dayjs,lodash → lodash-es 按需导入)
四、CSS 优化
1. 减少回流和重绘
/* 用 transform 替代 top/left 做位移动画 */
/* 不好 */
.box { top: 10px; } /* 触发回流 */
/* 好 */
.box { transform: translateY(10px); } /* 合成层,不触发回流 */
/* 用 opacity 替代 visibility/display 做淡入淡出 */
.fade { opacity: 0; transition: opacity 0.3s; }
2. 关键 CSS 内联
将首屏渲染所需的最小 CSS 内联到 <head> 中,非关键 CSS 异步加载:
<head>
<style>/* 关键CSS,<14KB */</style>
<link rel="preload" href="/non-critical.css" as="style" onload="this.rel='stylesheet'">
</head>
3. CSS 按需加载
- CSS Modules / Scoped CSS:避免全局样式污染
- Tailwind CSS Purge:构建时删除未用的工具类
@layer控制样式优先级,避免权重战
4. 减少 CSS 复杂度
- 避免深层嵌套选择器(增加计算成本)
- 避免通配符
*选择器 - 合并相同的
@media查询
五、图片与多媒体优化
图片格式选择
| 场景 | 推荐格式 |
|---|---|
| 照片 | AVIF / WebP(降级 JPEG) |
| 透明图片 | AVIF / WebP(降级 PNG) |
| 图标/线条图 | SVG |
| 动图 | WebP / AVIF(降级 GIF) |
<!-- 使用 <picture> 按格式降级 -->
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="描述" width="800" height="450">
</picture>
懒加载
<!-- 原生懒加载(浏览器支持 >95%) -->
<img src="large.jpg" loading="lazy" alt="...">
<!-- 视频懒加载 -->
<video loading="lazy" preload="none"></video>
图片尺寸优化
- 始终指定
width和height属性,防止 CLS - 用
object-fit: cover配合固定容器,避免图片撑开布局 - Next.js
<Image>/ Nuxt<NuxtImg>自动优化(格式转换、懒加载、占位符)
六、字体优化
1. 使用 font-display: swap
@font-face {
font-family: 'MyFont';
src: url('font.woff2') format('woff2');
font-display: swap; /* 先用系统字体,加载完再切换,避免 FOIT */
}
2. 只加载需要的字符集
- 中文字体体积巨大,使用字体子集化工具(
pyftsubset)只打包用到的字符 - Google Fonts 添加
text=参数指定需要的字符
3. 预加载关键字体
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
七、服务端与网络层优化
1. 服务端渲染(SSR)
- Next.js / Nuxt:服务端直接返回完整 HTML,显著提升 FCP 和 LCP
- 流式渲染(Streaming SSR):边渲染边传输,React 18 / Next.js App Router 支持
- 静态生成(SSG / ISR):预生成 HTML,CDN 分发,TTFB 最低
2. HTTP/2 / HTTP/3
- 确保服务器开启 HTTP/2(Nginx
listen 443 ssl http2) - HTTP/3 / QUIC 对弱网环境效果显著
3. 服务端压缩
# Nginx 配置
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1024;
# Brotli(需额外模块)
brotli on;
brotli_comp_level 6;
4. 资源 Preload / Push
- HTTP/2 Server Push(已逐渐被 103 Early Hints 替代)
103 Early Hints:在主响应前预先推送资源预加载指令
八、React / Vue 框架层优化
React 优化
// 1. memo 防止不必要的子组件渲染
const Child = React.memo(({ data }) => <div>{data}</div>);
// 2. useMemo 缓存计算结果
const sorted = useMemo(() => items.sort(compareFn), [items]);
// 3. useCallback 缓存函数引用(给子组件传函数时)
const handleClick = useCallback(() => { ... }, [dep]);
// 4. 列表必须有稳定的 key
{list.map(item => <Item key={item.id} {...item} />)}
// 5. 动态导入路由
const Page = lazy(() => import('./Page'));
Vue 优化
<!-- 1. v-once:静态内容只渲染一次 -->
<StaticComponent v-once />
<!-- 2. v-memo:缓存子树,仅依赖变化时更新 -->
<li v-for="item in list" :key="item.id" v-memo="[item.selected]">
<!-- 3. shallowRef / shallowReactive:浅层响应,减少 Proxy 开销 -->
const bigData = shallowRef(largeObject);
<!-- 4. computed 有缓存,避免模板中调用函数 -->
const sorted = computed(() => list.value.slice().sort());
九、监控与持续优化
线上性能监控(RUM)
// 使用 PerformanceObserver 采集真实用户数据
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.entryType === 'largest-contentful-paint') {
analytics.send('LCP', entry.startTime);
}
}
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
工具链
- Sentry Performance:错误 + 性能一体化监控
- Datadog RUM / New Relic:企业级全栈监控
- 自建上报:PerformanceObserver + 后端接收 + Grafana 可视化
性能预算(Performance Budget)
在 CI 中集成 Lighthouse,超过阈值则阻断部署:
# .github/workflows/ci.yml
- name: Lighthouse Check
uses: treosh/lighthouse-ci-action@v10
with:
budgetPath: ./budget.json
uploadArtifacts: true
十、性能优化清单
加载性能
- 开启 Gzip/Brotli 压缩
- 静态资源走 CDN
- JS/CSS/HTML 文件 minify
- 图片使用 WebP/AVIF 格式
- 图片指定 width/height 防止 CLS
- 图片懒加载(
loading="lazy") - 关键资源 preload
- 路由级代码分割
- 第三方库按需导入
- 去掉未使用的依赖
- 开启 HTTP/2
运行时性能
- 列表有稳定 key
- 合理使用 memo/useMemo/useCallback
- 长列表使用虚拟滚动
- 动画使用 transform/opacity
- scroll/resize 事件使用节流
- 搜索输入使用防抖
- 避免在循环中读写 DOM 布局属性
- CPU 密集任务移到 Web Worker
监控
- 接入 Lighthouse CI
- 线上 RUM 采集 Core Web Vitals
- 设置性能预算告警