首屏性能优化全链路
1. 全链路阶段
DNS 解析 → TCP 握手 → TLS 握手 → 首字节(TTFB) → HTML 下载 → 解析 → 关键资源 → FCP → LCP → 交互可用
10ms 30ms 80ms 200-500ms ~ parse blocking ~ ~ INP
每一段都有优化点。
2. DNS
- DNS prefetch:
<link rel="dns-prefetch" href="//api.example.com"> - preconnect:
<link rel="preconnect" href="https://api.example.com">提前 DNS + TCP + TLS - 减少域名数(HTTP/2 时代不要域名分片)
- 用快的 DNS(Cloudflare 1.1.1.1)
3. TCP / TLS
- HTTPS(启用 HTTP/2、HTTP/3)
- TLS 1.3 + 0-RTT
- session 复用
- OCSP Stapling
- 服务器开 BBR
详见模块 02、03。
4. TTFB(服务端响应)
- CDN 缓存(命中时 < 50ms)
- SSR 缓存(页面级、组件级)
- 数据库索引、N+1 查询
- 动态加速(CDN 厂商提供,BGP 多线 + TCP 优化)
TTFB 慢 → 后端慢 + 网络慢
排查:curl -w "TTFB: %{time_starttransfer}s\n" -o /dev/null -s URL
5. HTML 解析
5.1 减少阻塞
<!-- ✗ 默认 script 阻塞 HTML 解析 -->
<script src="/app.js"></script>
<!-- ✓ defer:解析完 HTML 后按顺序执行 -->
<script src="/app.js" defer></script>
<!-- ✓ async:下载完立即执行(无序,无依赖时用) -->
<script src="/analytics.js" async></script>
<!-- 模块 -->
<script src="/app.js" type="module"></script> <!-- 默认 defer -->
5.2 inline 关键 CSS
<head>
<style>
/* 首屏关键样式直接 inline */
.header { ... }
</style>
<link rel="preload" href="/full.css" as="style" onload="this.rel='stylesheet'">
</head>
工具:critical / penthouse 提取首屏 CSS。
6. 关键资源加载
6.1 preload
<link rel="preload" href="/font.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/hero.jpg" as="image">
<link rel="preload" href="/app.js" as="script">
告诉浏览器"这个最重要,立即下载"。
6.2 prefetch(次要资源)
<link rel="prefetch" href="/next-page.js">
空闲时下载,下个页面用。
6.3 modulepreload
<link rel="modulepreload" href="/main.js">
ES 模块专用 preload。
6.4 fetchpriority
<img src="hero.jpg" fetchpriority="high">
<img src="thumbnail.jpg" fetchpriority="low">
7. 资源优化
7.1 图片
- 格式:AVIF > WebP > JPEG
- responsive
srcset:
<img srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1600.jpg 1600w"
sizes="(max-width: 600px) 400px, 800px"
src="hero-800.jpg" alt="">
- 懒加载:
<img loading="lazy">(首屏图不要加,会延迟 LCP) - 占位:低质量预览(LQIP)/ blurhash
widthheight防 CLS
7.2 字体
@font-face {
font-family: 'Inter';
src: url('/inter.woff2') format('woff2');
font-display: swap; /* 字体加载前用回退字体 */
}
<link rel="preload" href="/inter.woff2" as="font" type="font/woff2" crossorigin>
7.3 JS
- 按路由代码分割(动态 import)
- Tree shaking
- Vendor 拆分(变化少的依赖单独缓存)
- minify + brotli
- 减依赖(lodash → lodash-es 按需 / 自己实现)
7.4 CSS
- 按需引入组件库(按 import)
- 移除未用 CSS(PurgeCSS、Tailwind JIT)
- atomic CSS(Tailwind / UnoCSS)
- 避免 @import 嵌套
8. 缓存
详见 HTTP 缓存体系。要点:
- hash 文件 + immutable
- HTML no-cache
- CDN 命中率 > 95%
9. SSR / SSG / ISR
| 渲染方式 | TTFB | SEO | 适合 |
|---|---|---|---|
| CSR(客户端) | 快(HTML 空壳) | 差 | 后台系统 |
| SSR(服务端) | 中 | 好 | 动态内容 |
| SSG(静态生成) | 极快 | 极好 | 营销页、博客 |
| ISR(增量再生) | 极快(CDN 命中) | 好 | 半静态(电商列表) |
Next.js / Nuxt 都支持四种。
10. 关键优化点排序(按 ROI)
- 启用 CDN(首屏减半)
- HTTPS / HTTP/2 / brotli
- 图片 WebP + 懒加载 + responsive
- 字体 woff2 + font-display: swap + preload
- JS 代码分割 + tree shaking
- SSR 缓存 / ISR
- 关键 CSS inline
- 减第三方脚本(统计 / 客服)
- preconnect / preload 关键域名和资源
- Service Worker 缓存(PWA)
11. 度量
LCP 目标 < 2.5s
INP 目标 < 200ms
CLS 目标 < 0.1
工具:
- Chrome DevTools → Lighthouse
- WebPageTest(多地点测试)
- Vercel Analytics
- 自建 RUM
12. 常见反模式
- 首屏图懒加载:LCP 反而变慢
- JS 全部同步阻塞:FCP 慢
- 不分代码:JS 几 MB 一次下完
- 第三方脚本无限制:客服 + 统计 + 广告 = 性能黑洞
- 不限制字体粗细:5 个 weight × 2 style 加载十几个字体文件
- CDN 命中率不监控:源站默默扛压
<img>不设 width/height:CLS- 优化只在桌面 lab 测:移动 4G 体感差距巨大
13. 延伸阅读
- web.dev - Fast
- 《Web 性能权威指南》Ilya Grigorik
- PageSpeed Insights
- WebPageTest
- 模块 02 / 03 / 09 各篇相关章节