extractcritical 返回空对象主因是html未加载完样式资源,如css路径404或缺base url;需内联css或显式传入,避免静态分析漏掉动态class,禁用@import等网络请求规则,并精准指定媒体查询。

提取 Critical CSS 时为什么 extractCritical 返回空对象?
常见现象是调用 extractCritical(来自 critters 或旧版 penthouse)后,css 字段为空或只含注释。根本原因不是代码写错,而是 HTML 输入没加载完样式资源——比如 <link rel="stylesheet"> 指向的 CSS 文件路径 404,或用了相对路径但解析上下文缺失 base URL。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 确保传入
extractCritical的 HTML 字符串已内联所有外部 CSS(或至少提供可访问的本地文件路径),critters默认不自动下载远程资源 - 用
fs.readFileSync预读 CSS 文件,再通过html: <string></string>+css: [<string>]</string>显式传入,绕过路径解析逻辑 - 检查是否误将 SSR 渲染后的 HTML(含动态 class)直接喂给工具——若首屏 DOM 结构依赖 JS 执行,
critters静态分析必然漏掉那些 class 对应的规则
critters 在 Vite / Webpack 中注入时机不对怎么办?
典型表现:生成的 Critical CSS 包含大量非首屏样式(如 .modal-hidden、.user-dropdown--closed),甚至把整个 node_modules 里的 CSS 都塞进去了。这是因为构建时 HTML 模板还没经过组件实际渲染,工具只能看到原始模板中的 class,而不知道哪些会在首屏真实出现。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 不要在构建阶段静态提取,改用运行时服务端渲染(SSR)后抓取真实首屏 HTML,再喂给
critters——例如 Next.js 用getStaticProps+renderToStaticMarkup预生成 HTML 片段 - 若必须构建时提取,限定范围:用
include选项只处理内特定容器(如#app),并配合pruneSource剔除未匹配选择器 - 避免对
global.css全量提取;拆分样式:首屏专用critical.css单独 import,其余走 lazy CSS
内联 Critical CSS 后页面闪动(FOUC)更严重?
这不是 Critical CSS 本身的问题,而是加载顺序冲突:你把提取出的样式内联了,但原有 <link> 标签还在,浏览器会先渲染内联样式,等外部 CSS 加载完又重绘一次。更糟的是,如果内联样式里用了 @import 或字体声明,反而拖慢渲染。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 务必移除对应页面中所有被提取过的
<link rel="stylesheet">标签,否则等于白干 - 禁止在 Critical CSS 块里写
@font-face、@import、url()等触发网络请求的规则;这些该保留在延迟加载的主 CSS 中 - 用
media属性做条件加载:比如<style media="print">...</style>不参与首屏渲染,但能避免阻塞;真正首屏样式用media="all"或不设 media
移动端适配时 min-width 媒体查询总被漏掉?
critters 默认只分析无媒体查询或 screen 类型的规则,像 @media (min-width: 768px) 这种响应式断点,若首屏 HTML 在桌面环境下生成,就可能被跳过——即使你在手机上打开,工具也不知道“这个断点会在首屏生效”。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 显式传入
options.mediaQueries: ['all', '(min-width: 320px)', '(min-width: 768px)'],告诉工具哪些 MQ 必须纳入分析 - 避免嵌套 MQ:
@media (prefers-color-scheme: dark) { @media (min-width: 768px) { ... } }这类结构critters当前版本无法识别,得扁平化 - 测试时用真实设备宽度截图比对:提取前后首屏像素级渲染结果,别只信 devtools 里的 computed styles
关键点在于:Critical CSS 不是“越多越好”,而是“刚好够用”。漏掉一个首屏按钮的 hover 样式,用户可能点两下才意识到它可交互;多塞一个折叠菜单的 closed 状态样式,反而让首屏体积上涨 30%。这事没法全自动,得靠真实设备 + 真实网络环境反复验证。











