# 前端性能优化 (Frontend Performance)
> 💡 **学习指南**:本章节无需深入的算法背景,通过交互式演示带你掌握前端性能优化的核心逻辑。我们将从最直观的页面加载讲起,一直到浏览器底层的渲染机制和缓存策略。
```
---
## 6. 字体优化
字体也会影响性能,不当的字体加载会导致 FOUT/FOIT。
### 6.1 Web Font 优化
**问题**:使用 Web Font 时,浏览器可能:
- **FOUT**(Flash of Unstyled Text):先显示系统字体,然后切换到 Web Font
- **FOIT**(Flash of Invisible Text):文字隐藏,等 Web Font 加载完才显示
### 6.2 Font Display 策略
```css
@font-face {
font-family: 'MyFont';
src: url('myfont.woff2') format('woff2');
font-display: swap; /* 立即显示系统字体,Web Font 加载完再切换 */
}
```
**`font-display` 值**:
- `auto`:浏览器默认
- `swap`:立即显示文本,Web Font 加载后替换(推荐)
- `fallback`:短时间隐藏,超时后显示系统字体
- `optional`:如果 Web Font 加载慢,就不使用它
### 6.3 字体子集化
**只包含用到的字符**:
- 中文字体很大(几 MB),但通常只用几百个字
- 使用工具提取子集
**工具**:
- **Fontmin**(中文字体子集化)
- **glyphhanger**(提取页面实际使用的字符)
**示例**:
```bash
# 只提取常用的 500 个汉字
fontmin input.ttf output/ --text='常用的五百个汉字...'
```
**结果**:
- 原始字体:5 MB
- 子集化后:200 KB
- 减少 96%
---
## 7. 缓存策略
缓存是性能优化的"银弹",用好了能极大提升性能。
### 7.1 HTTP 缓存
**强缓存(Strong Cache)**:
```nginx
# 静态资源缓存 1 年
location ~* \.(jpg|png|css|js)$ {
expires: 1y;
add_header Cache-Control: public, immutable;
}
```
**协商缓存(Conditional Cache)**:
```nginx
# 使用 ETag
location / {
etag on;
}
```
**最佳实践**:
- 带哈希的文件名(如 `app.abc123.js`):永久缓存
- 不带哈希的文件:协商缓存
### 7.2 Service Worker
**Service Worker**:在浏览器后台运行的脚本,可以拦截网络请求
**核心能力**:
- 离线访问
- 资源缓存
- 后台同步
**示例**(使用 Workbox):
```javascript
// 注册 Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
}
// sw.js (Service Worker 脚本)
workbox.routing.registerRoute(
/\.(?:png|jpg|jpeg|svg|gif)$/,
new workbox.strategies.CacheFirst({
cacheName: 'images',
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60 // 30 天
})
]
})
)
```
### 7.3 LocalStorage / IndexedDB
**LocalStorage**:存储简单数据(5-10 MB)
```javascript
// 缓存 API 数据
localStorage.setItem('cache_key', JSON.stringify(data))
const cached = JSON.parse(localStorage.getItem('cache_key'))
```
**IndexedDB**:存储大量结构化数据
```javascript
// 存储离线数据
const db = await openDB('mydb', 1, {
upgrade(db) {
db.createObjectStore('posts')
}
})
await db.put('posts', postData, 'post-1')
```
---
## 8. 监控与持续优化
性能优化不是一次性的工作,需要持续监控和改进。
### 8.1 Real User Monitoring (RUM)
**RUM**:收集真实用户的性能数据
**工具**:
- **Google Analytics**:免费,基础数据
- **Cloudflare Web Analytics**:免费,注重隐私
- **SpeedCurve**:付费,专业级
**关键指标**:
- 首屏时间(FCP、LCP)
- 交互时间(TTI)
- 转化率与性能的关系
### 8.2 Synthetic Monitoring
**合成监控**:用模拟用户定期测试
**工具**:
- **Lighthouse CI**:每次提交代码自动测试
- **WebPageTest**:定期测试关键页面
- **Pingdom**:简单易用的监控服务
### 8.3 性能预算
**设置预算并强制执行**:
```javascript
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router'],
ui: ['element-plus']
}
}
}
}
})
```
**使用 Lighthouse CI 检查预算**:
```json
// lighthouserc.json
{
"ci": {
"assert": {
"preset": "desktop",
"assertions": {
"first-contentful-paint": ["warn", { "maxNumericValue": 2000 }],
"interactive": ["error", { "maxNumericValue": 5000 }]
}
}
}
}
```
---
## 9. 实战案例
### 9.1 案例 1:新闻列表页优化
**问题**:首屏加载慢,滚动卡顿
**优化**:
1. **图片**:WebP + 懒加载
2. **列表**:虚拟列表(只渲染可见的 10 项)
3. **数据**:分页加载
**结果**:LCP 2.5s -> 0.8s
### 9.2 案例 2:数据可视化大屏
**问题**:渲染大量节点卡死
**优化**:
1. **渲染**:Canvas 代替 DOM
2. **计算**:Web Worker 处理数据
**结果**:FPS 10 -> 60
### 9.3 案例 3:移动端活动页
**问题**:白屏时间长
**优化**:
1. **资源**:预加载 (Preload) 关键图
2. **体验**:骨架屏 (Skeleton)
**结果**:白屏减少 60%
---
## 10. 总结与最佳实践
### 10.1 性能优化清单
**加载优化**:
- ✅ 启用 Gzip/Brotli 压缩
- ✅ 使用 CDN 加速静态资源
- ✅ 实施代码分割和懒加载
- ✅ 压缩和优化图片
**渲染优化**:
- ✅ 减少重排和重绘
- ✅ 优化关键渲染路径
- ✅ 使用 CSS 动画代替 JS 动画
**执行优化**:
- ✅ 使用 Web Workers 处理重计算
- ✅ 避免长任务(Long Tasks)
- ✅ 合理使用防抖和节流
**缓存优化**:
- ✅ 配置 HTTP 强缓存和协商缓存
- ✅ 考虑使用 Service Worker
### 10.2 持续学习
前端性能优化是一个不断发展的领域,新的标准(如 INP)和新的工具(如 Vite, Turbopack)层出不穷。保持好奇心,多看 Performance 面板,是你最好的老师。
---
## 11. 名词速查表 (Glossary)
| 名词 | 全称 | 解释 |
| :--- | :--- | :--- |
| **FP / FCP** | First Paint / First Contentful Paint | **首屏时间**。用户看到页面第一个像素/第一块内容的时间。 |
| **LCP** | Largest Contentful Paint | **最大内容绘制**。页面主要内容加载完成的时间(衡量加载速度的核心指标)。 |
| **INP** | Interaction to Next Paint | **交互到下一次绘制**。衡量页面响应速度的新指标(替代 FID),关注点击后的反馈延迟。 |
| **CLS** | Cumulative Layout Shift | **累积布局偏移**。页面加载时元素乱跳的程度(衡量视觉稳定性)。 |
| **TTFB** | Time to First Byte | **首字节时间**。从发出请求到接收到服务器第一个字节的时间(衡量后端响应速度)。 |
| **TBT** | Total Blocking Time | **总阻塞时间**。主线程被长任务阻塞的总时间(衡量页面交互流畅度)。 |
| **Reflow** | Reflow (Layout) | **重排**。浏览器重新计算元素位置和大小的过程。成本高,应避免。 |
| **Repaint** | Repaint | **重绘**。浏览器重新绘制元素外观(如颜色)的过程。成本中等。 |
| **CDN** | Content Delivery Network | **内容分发网络**。把文件存在离用户最近的服务器上,加速下载。 |
| **SSR** | Server-Side Rendering | **服务端渲染**。在服务器端生成 HTML,加快首屏显示,利于 SEO。 |
| **CSR** | Client-Side Rendering | **客户端渲染**。在浏览器端通过 JS 生成 HTML,交互体验好,但首屏慢。 |
| **SSG** | Static Site Generation | **静态站点生成**。构建时生成静态 HTML,访问速度极快。 |
| **Tree Shaking** | Tree Shaking | **摇树优化**。构建时移除未使用的代码,减小包体积。 |
| **Code Splitting** | Code Splitting | **代码分割**。将代码拆分成小块,按需加载。 |
| **Preload / Prefetch** | Preload / Prefetch | **预加载/预获取**。提前告知浏览器加载关键资源或未来可能用到的资源。 |