critical cli 提取空 css 主因是工具未获取真实首屏样式:默认不加载远程 css、路径错误、动态 class 未渲染、@import 未展开;需显式传入本地 css 字符串、限定分析范围(如 include: '#app')、确保 html 为 ssr 渲染后的完整快照。

critical CLI 提取后返回空 CSS 怎么办
工具看到的 HTML 根本没加载样式资源,不是命令写错。critical 默认不下载远程 <link rel="stylesheet">,一旦路径 404、缺 <base>、或 CSS 文件还没生成到 dist/ 目录,就解析不出任何规则。
- 用
fs.readFileSync('dist/style.css', 'utf8')读取本地 CSS 字符串,显式传给critical的--css参数,绕过网络请求环节 - 确保传入的 HTML 是 SSR 渲染后的完整快照(比如从
dist/index.html读取),而非开发时的空模板 - 加
--prune-source true --include '#app',限制分析范围,避免扫进node_modules里未用的样式 - 若用 SPA 路由,必须显式访问对应路径,例如
critical http://localhost:5173/product --target product-critical.html,不能只跑根路径
为什么提取的 Critical CSS 在手机端反而拖慢 FCP
按桌面宽屏(如 width: 1300)提取后直接用于移动端,会塞进大量 @media (min-width: 1200px) 规则,体积虚高、命中率低,gzip 后超 14KB 还会拖慢 TTFB。
- 必须按目标设备视口模拟:移动端优先用
--width 375 --height 667(iPhone SE)或--width 414 --height 896(iPhone 12) - 务必过滤掉
@font-face、@keyframes和display: none元素的样式——它们不参与首屏渲染 - 禁用条件渲染的 loading skeleton,例如不要在 SSR 阶段用
{isLoading ? <skeleton></skeleton> : <content></content>},否则提取器只看到<skeleton></skeleton>的 DOM
内联 Critical CSS 后页面闪动(FOUC)更严重
这不是 Critical CSS 本身的问题,是加载链冲突了:你把样式内联了,但原来的 <link rel="stylesheet" href="style.css"> 还在 DOM 里,浏览器先画一次内联样式,等外部 CSS 加载完又重绘一遍。
- 必须从 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'"
Vite/Next.js 构建时提取的 Critical CSS 里全是 .modal-hidden 这类规则
原因很实在:构建时 HTML 模板还没被组件真正渲染,插件只能看到原始字符串里的 class,没法知道哪些会在 hydration 前真实挂载。
- SSR 场景(如 Next.js、Nuxt)优先在
getStaticProps或generateStaticParams里用renderToStaticMarkup预生成真实首屏 HTML 片段,再喂给critters - 若必须构建时提取,限定范围:
include: 'body > #root'+pruneSource: true,并拆分样式:首屏专用critical.css单独import,其余走 lazy CSS - Vite 项目推荐直接用
vite-plugin-critters,它会接管 HTML 构建流程,自动移除原始<link>,比手动加critters()更可靠
.is-loading 或 .active。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











