跳到主要内容

首屏性能优化全链路

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
  • width height 防 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

渲染方式TTFBSEO适合
CSR(客户端)快(HTML 空壳)后台系统
SSR(服务端)动态内容
SSG(静态生成)极快极好营销页、博客
ISR(增量再生)极快(CDN 命中)半静态(电商列表)

Next.js / Nuxt 都支持四种。

10. 关键优化点排序(按 ROI)

  1. 启用 CDN(首屏减半)
  2. HTTPS / HTTP/2 / brotli
  3. 图片 WebP + 懒加载 + responsive
  4. 字体 woff2 + font-display: swap + preload
  5. JS 代码分割 + tree shaking
  6. SSR 缓存 / ISR
  7. 关键 CSS inline
  8. 减第三方脚本(统计 / 客服)
  9. preconnect / preload 关键域名和资源
  10. 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. 延伸阅读