太长不看 (TL;DR): CSS 默认会阻塞渲染。关键 CSS 内联(Critical CSS inlining)将首屏样式提取放入
<head>中,通过异步加载完整的 CSS 来消除阻塞渲染的网络请求。本指南涵盖了常用的提取工具、内联体积阈值以及异步加载模式。以上策略均已在 tanstackship.com 获取实际应用。
引言
每个外部 CSS 文件都会增加一次阻塞页面渲染的往返请求。内联关键 CSS(即初始视口内容所需的样式)可以为首次绘制消除这些往返请求,从而极大地提升最大内容绘制(Largest Contentful Paint,简称 LCP)。
关键 CSS 的工作原理
| 方案 | 首次绘制 (First Paint) | 实施复杂度 | 维护成本 |
|---|---|---|---|
<head> 中的完整 CSS | 即时 | 无(全部内联) | CSS 无法被缓存 |
| 提取的关键 CSS | 几乎即时 | 中等 | 需要构建步骤 |
| HTTP/2 服务器推送 | 快速 | 低 | Chrome 中已被弃用 |
| 内联 + 异步加载完整 CSS | 几乎即时 | 中等 | 最佳平衡点 |
| 关键 CSS + 预加载 (preload) | 即时 | 高 | 最优的生产环境配置 |
关键 CSS 提取
// 使用 critical 包在构建时进行提取
import { generate } from 'critical'
await generate({
base: 'dist/',
src: 'index.html',
target: 'index.html',
inline: true,
width: 1440,
height: 900,
extract: true,
})
这会生成一个 index.html,其中关键样式已被内联,并且完整的 CSS 将被异步加载。
异步 CSS 加载模式
<!-- 在 <head> 中内联的关键 CSS -->
<style>
/* 大约 15KB 的首屏样式 */
header, nav, .hero { ... }
</style>
<!-- 异步加载完整 CSS -->
<link rel="preload" href="/assets/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/assets/styles.css"></noscript>
生产环境实现
// TanStack Start:关键 CSS 中间件
import { defineMiddleware } from '~/lib/middleware'
export const criticalCSSMiddleware = defineMiddleware({
async after({ response }) {
if (response.headers.get('Content-Type')?.includes('text/html')) {
const html = await response.text()
const criticalCSS = extractCriticalCSS(html)
const optimized = html.replace(
'</head>',
`<style id="critical-css">${criticalCSS}</style>
<link rel="preload" href="/assets/styles.css" as="style"
onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/assets/styles.css"></noscript>
</head>`
)
return new Response(optimized, response)
}
}
})
内联体积阈值指南
| 场景 | 最大内联 CSS 体积 | 性能影响 |
|---|---|---|
| 移动端 (3G) | 10-15 KB | 节省 300-800ms |
| 桌面端 (WiFi) | 20-30 KB | 节省 100-300ms |
| 首次访问 | 越小越好 | 获益最大 |
| 回访 | 交由缓存处理 | 影响较小 |
结论
关键 CSS 内联是投资回报率最高的性能优化手段之一。在构建时提取首屏样式,将它们内联到 <head> 中,并异步加载完整的样式表。此举能够彻底消除阻塞渲染的 CSS 请求,并为你带来几乎瞬间的首屏绘制体验。
如需了解可互补的性能优化模式,请参阅我们的 Web 应用程序字体加载策略和 Preload、Prefetch 与 Preconnect 预加载指南 —— 它们共同覆盖了完整的关键渲染路径。结合 降低首字节时间 (TTFB) 以及 核心 Web 指标 (Core Web Vitals) 优化指南,为你打造全面的性能优化策略。