内联 critical css 有效但需精准提取、控体积、避冲突;extractcritical 返回空因html未含真实样式;fouc源于内联与外链共存;构建时提取易误判首屏样式;超14kb gzip会拖慢ttfb。

内联 Critical CSS 是解决首屏渲染阻塞最直接有效的手段,但前提是提取准、体积控得住、加载链不冲突——否则反而拖慢 TTFB 或引发 FOUC。
extractCritical 返回空 css 字段怎么办
这是工具链中最常见的“假失败”,不是代码写错,而是输入 HTML 没带进真实样式资源。 -extractCritical(来自 critters 或旧版 penthouse)默认不下载远程 <link rel="stylesheet">,若路径 404 或缺 <base>,就解析不出规则
- SSR 渲染后的 HTML 若含动态 class(如 class="btn btn--primary is-loading"),而工具只看到模板里的 btn,就会漏掉 is-loading 对应的样式
- @import 未提前用 postcss-import 展开,critters 直接跳过整条规则
实操建议:
- 用
fs.readFileSync把 CSS 文件读成字符串,显式传给extractCritical的css参数,绕过路径解析 - 确保传入的 HTML 字符串已内联全部基础样式,或至少是本地可访问的完整快照
- 静态提取时加
pruneSource: true+include: '#app',限制分析范围,避免把node_modules里未用的样式也扫进来
critical CLI 提取后页面闪动(FOUC)更严重
这不是 Critical CSS 本身的问题,而是加载逻辑打架了。 - 内联块生效了,但原来的<link rel="stylesheet" href="style.css"> 还在 DOM 里,浏览器会先画一次内联样式,等外部 CSS 加载完再重绘一遍
- 更糟的是,如果内联块里混进了 @font-face 或 url(/img/hero.jpg),这些会同步触发网络请求,卡死 CSSOM 构建
实操建议:
- 必须从 HTML 中彻底移除所有被提取覆盖的
<link>标签,不能只靠内联就以为万事大吉 - 内联块里禁止出现:
@import、@font-face、任何含url()的声明;这些该留在非关键 CSS 中,用rel="preload"控制加载时机 - 非关键 CSS 推荐用
media="print"hack + JS onload 切换,或直接rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'"
Webpack/Vite 中 critical 插件注入时机不对
典型表现是生成的 Critical CSS 里塞满了.modal-hidden、.user-dropdown--closed 这类根本不在首屏出现的规则。
原因很实在:构建时 HTML 模板还没被组件真正渲染,插件只能看到原始字符串里的 class,没法知道哪些会在 hydration 前真实挂载。
实操建议:
- SSR 场景(如 Next.js、Nuxt)优先在
getServerSideProps或generateStaticParams阶段调用critical,喂给它真实渲染出的 HTML 字符串 - 若必须构建时提取,禁用全局样式全量扫描,改用
include: ['header', 'main:first-of-type']显式限定容器 - 拆分样式源:把首屏专用规则单独写进
critical.css,其余走import('./async.css')动态加载,别让工具去猜
内联体积超 14KB(gzip 后)还有效吗
基本无效,甚至有害。 - 浏览器对内联<style></style> 的解析是同步阻塞的,体积越大,HTML 解析越慢,TTFB 越高
- HTTP/2 下,小体积内联 + 外链 CSS 并行加载收益最大;超载后,外链 CSS 反而要等 HTML 解析完才能发起请求
- Lighthouse 的「Eliminate render-blocking resources」警告常源于此:你本想消除阻塞,结果造了个更大的阻塞点
实操建议:
- 提取后务必用
gzip-size检查最终体积,目标控制在gzip后 ≤14KB - 若超限,优先砍掉媒体查询冗余(比如同时保留
@media (min-width: 768px)和@media (min-width: 1024px)中重复规则) - 不要为“兼容暗色模式”把整套
@media (prefers-color-scheme: dark)都塞进去——只留首屏元素在暗色下实际变化的那几条声明
真正难的从来不是“怎么内联”,而是判断“哪些该进、哪些必须踢出去”。工具能跑通流程,但语义理解还得靠人盯住首屏 DOM 结构、媒体查询匹配状态、以及 JS 是否已介入 class 切换。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











