第 14 章 · 性能优化与浏览器调试
本章目标:使用 Chrome DevTools、Lighthouse 分析 academy-demo 性能瓶颈,掌握 缓存、图片优化、防抖节流 等实战手段,建立「测量 → 优化 → 再测量」的工作流。
前置:第 9~13 章;已能用 Vite 构建 academy-demo。
14.1 性能指标体系
| 指标 | 含义 | 良好参考(移动端) |
|---|
| LCP | 最大内容绘制 | < 2.5s |
| INP | 交互到下一帧 | < 200ms |
| CLS | 累积布局偏移 | < 0.1 |
| FCP | 首次内容绘制 | < 1.8s |
| TTFB | 首字节时间 | < 800ms |
行业案例 · 贤紫优选商城:商品列表 LCP 3.8s,Lighthouse 诊断为首屏加载 1.2MB 未压缩图。WebP + 懒加载 + CDN 缓存后 LCP 1.6s,转化率提升 7%。
14.2 Lighthouse 使用流程
- Chrome 打开 academy-demo 生产构建:
npm run build && npm run preview
- F12 → Lighthouse 面板
- 模式:Navigation;设备:Mobile;类别:Performance、Accessibility
- 生成报告,记录分数与 Opportunities
| 报告区块 | 关注点 |
|---|
| Opportunities | 可自动估算收益的优化项 |
| Diagnostics | 深层原因(主线程、DOM 规模) |
| Passed audits | 已达标项,避免重复劳动 |
目标:academy-demo 首页 Performance ≥ 85(移动端),Accessibility ≥ 90。
14.3 Network 面板调试
瀑布图阅读顺序:
DNS → 连接 → SSL → 等待(TTFB) → 下载(Content Download)
| 功能 | 快捷键/操作 | 用途 |
|---|
| 禁用缓存 | Disable cache(DevTools 打开时) | 模拟首次访问 |
| 限速 | Fast 3G / Slow 4G | 弱网体验 |
| 筛选 | Img / JS / Fetch/XHR | 定位大资源 |
| Initiator | 点击请求看调用栈 | 谁发起了请求 |
14.3.1 academy-demo 排查清单
| 检查项 | 标准 |
|---|
| JS 总体积 | 单页 < 200KB gzip(入门项目) |
| 图片单张 | 头图 < 150KB |
| API 请求 | 课程列表 1 次,避免瀑布式 N+1 |
| 重复请求 | 切换 Tab 不应重复拉全量 |
14.4 浏览器缓存策略
| 类型 | 机制 | 适用资源 |
|---|
| 强缓存 | Cache-Control: max-age | 带 hash 的 JS/CSS |
| 协商缓存 | ETag / Last-Modified | 偶尔更新的 JSON |
| Service Worker | 编程式缓存 | PWA(进阶) |
Vite 构建产物示例:
assets/main-a1b2c3d4.js → max-age=1y, immutable
index.html → no-cache(入口常更新)
Nginx 配置片段:
location ~* \.(js|css|png|jpg|webp|svg|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location = /academy-demo/index.html {
add_header Cache-Control "no-cache";
}
注意:开发时 DevTools 勾选 Disable cache;生产靠文件名 hash 破缓存。
14.5 图片优化
| 手段 | 说明 | academy-demo 应用 |
|---|
| 合适格式 | 照片 WebP/AVIF,图标 SVG | 头像、课程封面 |
| 响应式 | srcset + sizes | 移动端小图 |
| 懒加载 | loading="lazy" | 列表下方图片 |
| 尺寸 | 显示多大存多大 | 避免 4000px 缩到 120px |
| 占位 | 宽高属性防 CLS | width height 必填 |
<img
src="assets/avatar-240.webp"
srcset="assets/avatar-120.webp 120w, assets/avatar-240.webp 240w"
sizes="(max-width: 600px) 120px, 240px"
alt="学员头像"
width="120"
height="120"
loading="lazy"
decoding="async"
>
// 动态 WebP 检测(可选)
const supportsWebp = document.createElement('canvas')
.toDataURL('image/webp').startsWith('data:image/webp');
14.6 JavaScript 性能
14.6.1 减少主线程工作
| 问题 | 方案 |
|---|
| 大列表渲染 | 虚拟滚动或分页 |
| 频繁 DOM 读写 | 批量更新、DocumentFragment |
| 长任务 > 50ms | 拆分任务、requestIdleCallback |
| 重复计算 | 缓存结果、Memo |
// 批量渲染课程卡
function renderCourses(container, courses) {
const frag = document.createDocumentFragment();
for (const c of courses) {
frag.appendChild(createCourseCard(c));
}
container.replaceChildren(frag);
}