extractCritical 返回空是因为未正确加载CSS或HTML中动态class未被识别;内联后闪屏是因残留link标签导致重绘;首屏白屏源于关键CSS提取不准确或体积过大。

extractCritical 返回空、内联后反而闪屏、首屏还是白屏——不是工具不行,是输入没对。
为什么 extractCritical 总是返回空 CSS
它根本没看到真实样式:默认不加载 ,路径 404、 缺失、CSS 文件还没生成到 dist/ 目录,就解析不出任何规则。更常见的是 SSR 渲染的 HTML 含动态 class(比如 class="card card--featured is-animated"),但提取器只扫描模板里写的 card,漏掉 is-animated 对应的样式;或者 @import 没被 postcss-import 展开,整条规则直接跳过。
- 用
fs.readFileSync('./dist/style.css', 'utf8')把本地 CSS 读成字符串,显式传给extractCritical的css参数,绕过路径解析 - 确保传入的 HTML 是 SSR 完整渲染后的快照(比如从
dist/index.html读取),而非原始模板 - 加
pruneSource: true和include: '#app',限制分析范围,避免扫进node_modules里未用的样式
critters 在 Vite/Next.js 中提取结果不准怎么办
构建时插件看到的只是模板字符串里的 class,不是 hydration 前真实挂载的 DOM。所以生成的 Critical CSS 里塞满 .modal-hidden、.user-dropdown--closed 这类根本不在首屏出现的规则。
- SSR 场景(如 Next.js)优先在
getStaticProps或generateStaticParams里用renderToStaticMarkup预生成真实首屏 HTML 片段,再喂给critters - 若必须构建时提取,限定范围:
include: 'body > #root'+pruneSource: true,并拆分样式:首屏专用critical.css单独import,其余走 lazy CSS - 禁用条件渲染的 loading skeleton——比如不要在 SSR 阶段用
{isLoading ?,否则提取器只看到: } 的 DOM
内联后页面反而闪动(FOUC)更严重
这不是 Critical CSS 的问题,是加载链冲突了:你把样式内联了,但原来的 还在 DOM 里,浏览器先画一次内联样式,等外部 CSS 加载完又重绘一遍。更糟的是,如果内联块里混进了 @font-face 或 url(/img/hero.jpg),这些会同步触发网络请求,卡死 CSSOM 构建。
- 必须从 HTML 中彻底移除所有被提取覆盖的
标签,不能只靠内联就以为万事大吉 - 内联块里禁止出现:
@import、@font-face、任何含url()的声明;这些该留在非关键 CSS 中,用rel="preload"控制加载时机 - 非关键 CSS 推荐用
media="print"+onload="this.media='all'",或rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'"
体积和验证:别信“≤14KB”,要盯真实首屏
TCP 初始拥塞窗口虽约 14.6KB(压缩后),但这是理想上限;实际建议控制在 1KB 以内,尤其对移动端和弱网环境更敏感。超过该体积会导致额外 RTT,反而延迟首屏渲染。内联 CSS 不参与缓存,每次请求都重传;非关键 CSS 必须保留外部文件形式才能启用 HTTP 缓存。
- 打开 Chrome DevTools → Elements 面板 → 选中首屏任意元素 → 查看右侧 Styles 标签页,确认所有声明来源是
块,而非外部文件 - 检查是否真被样式覆盖:常见问题是选择器权重不足,或被后续
中同名规则覆盖(比如提取出.header { color: #333 },但页面末尾又载入 reset.css 把color设为inherit) - 移动端首屏样式和桌面端完全不同,用
width: 1300提取出来的规则,90% 在手机上根本不会触发
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











