critters在vite中必须配合ssr或预渲染才能生效,否则因无真实dom快照而提取失败;需用vite-plugin-critters、手动移除原link标签,并确保首屏dom结构与js执行结果一致。

关键 CSS 必须内联,但不能靠手工复制粘贴——漏掉 .btn:hover 或 .nav[open] 就会导致首屏可交互区域样式错乱;自动化提取不是“选个工具就行”,而是得匹配你的构建链路和首屏 DOM 真实结构。
critters 在 Vite 里怎么配才真正生效
很多人装了 critters 却没生成内联样式,根本原因是 Vite 默认不预渲染 HTML,critters 没有 DOM 快照可分析。它不是靠正则扫 CSS 文件,而是模拟浏览器加载首屏 HTML 后计算样式覆盖率。
- 必须开启
build.ssr: true或使用vite-plugin-prerender提前生成静态 HTML 快照,否则 critters 只看到空 - Vite 用户推荐直接用
vite-plugin-critters(非官方但维护活跃),它会自动接管 HTML 构建流程,比手动加critters()插件更稳 - 如果项目用了
router.push动态加载首屏内容(比如异步组件),得在 prerender 阶段显式访问对应路由,例如prerenderRoutes: ['/'],否则 critters 不知道该抓哪块 DOM - 输出的
<style data-critters></style>会被自动插入,但注意:它不会删掉原始<link rel="stylesheet">,你得手动移除或用插件配置inlineFonts: false避免重复
Webpack 项目中 critical 和 CrittersPlugin 的实际差异
critical 命令行工具适合 CI/CD 阶段跑一次生成,CrittersPlugin 是构建时集成。两者都依赖真实 URL,但触发时机和可控性不同。
-
critical要求服务已启动(如http://localhost:8080),超时默认 30s,SPA 页面常因 JS 未就绪导致提取不全,建议加--timeout 60000并等window.__INITIALIZED__ = true后再提取 -
CrittersPlugin直接读取打包后的 HTML 字符串,不依赖运行时服务,但无法感知 JS 渲染后的 DOM —— 如果首屏依赖 React/Vue mount 后才出现的元素,它大概率漏提 - 两者都不处理
@import规则:若你的app.css里写了@import 'base.css',critters 不会去解析base.css,得确保所有关键规则都在主入口 CSS 里 - 输出都是纯 CSS 字符串,注入 HTML 时务必手动加上
type="text/css",否则某些旧版 Safari 会忽略
非关键 CSS 延迟加载时 media="print" onload 的坑
这个 hack 能让浏览器跳过初始加载,但容易引发 FOUC 或媒体查询失效,尤其在暗色模式、响应式断点切换时。
-
media="print"确实阻止初始加载,但 onload 触发时机不可控:如果 CSS 文件 404 或网络慢,this.media='all'永远不执行,页面永远没样式 - 更稳妥的是监听
DOMContentLoaded后动态创建<link>:const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = '/non-critical.css'; document.head.append(link); - 若需支持媒体查询(如
media="(min-width: 768px)"),不能删掉原<link>标签,而应保留并改用rel="preload" as="style" onload="this.rel='stylesheet'",否则断点逻辑丢失 - 注意
onload回调里要清空自身引用:onload="this.onload=null;this.rel='stylesheet'",否则可能被多次触发
真正难的不是提取那几 KB 关键 CSS,而是确认首屏 DOM 在 JS 执行前后是否一致——如果导航栏是 JS 动态插入的,或者按钮状态靠 :has() 计算,所有自动化工具都会误判。这时候得退回去,用 Chrome Coverage 面板人工校验,再补白名单。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











