critters 比 penthouse 更适合现代构建流程,因其直接操作 html ast,无需启动浏览器,构建快、内存低、兼容 vite/webpack;penthouse 则依赖 chrome 实例,ci 易超时失败。

critters 为什么比 Penthouse 更适合现代构建流程
因为 critters 直接操作 HTML AST,不依赖截图或 Puppeteer 启动浏览器,构建快、内存占用低、Vite/Webpack 均原生兼容。Penthouse 虽准确但慢——每次都要启动 Chrome 实例、渲染首屏、提取覆盖样式,CI 环境下容易超时或失败。
常见错误现象:Penthouse 在无头环境里报 Failed to launch browser;critters 却在 Vite 构建中静默完成,连 console.log 都不用加。
-
critters默认跳过@import和外部字体请求,避免因跨域字体阻塞关键路径 - 它只处理
<link rel="stylesheet">,不碰<style></style>标签或内联style属性——这点必须手动确认项目没混用动态插入的<link> - 若用了 CSS-in-JS(如 Emotion),得额外配置服务端渲染入口,否则提取结果为空:比如在 Next.js 中需导出
getCriticalCSS()函数供 critters 调用
Vite 中启用 critters 的最小可行配置
不是装完就生效——它必须挂到 build.rollupOptions.plugins 上,且顺序要靠前,否则可能被其他插件(如 vite-plugin-html)提前写死 HTML。
典型错误:把 critters() 放在 react() 后面,结果 <style data-critters></style> 没注入,<link rel="preload"> 却生成了两次。
- 安装:
npm install critters --save-dev - 配置位置必须是
vite.config.ts的build.rollupOptions.plugins数组开头 - 不要设置
critters({ preload: false })——默认开启 preload 是为了触发 HTTP/2 优先级调度,关了反而拖慢 CSSOM 构建 - 输出 HTML 中会出现类似结构:
<style data-critters>h1{font-size:24px}</style> <link rel="preload" as="style" href="/assets/style.abc123.css" onload="this.onload=null;this.rel='stylesheet'">
非关键 CSS 延迟加载时 media="print" 的坑与绕过方式
很多人抄了 media="print" onload="this.media='all'" 就以为万事大吉,但实际会遇到 FOUC(闪白)、媒体查询失效、甚至 onload 不触发的问题。
根本原因:浏览器对 media="print" 的资源仍会发起请求(只是不应用),而某些 CDN 或代理会缓存该请求并返回空响应,导致 onload 永不触发。
- 更稳妥的做法是用
requestIdleCallback动态插入:link.rel = 'stylesheet',确保 DOM 就绪且主线程空闲后再加载 - 如果页面有暗色模式切换逻辑,别只靠
prefers-color-scheme媒体查询——那些规则必须保留在关键 CSS 里,否则首次渲染就是错的 - 响应式断点(如
min-width: 768px)不能全扔进非关键 CSS,否则移动端首屏会漏掉基础布局规则 - 注意
onload回调里必须清空自身:this.onload = null,否则切换路由后再次执行会重复 rel 切换
内联体积超 14KB 时的实际影响
不是“超过就一定变慢”,而是解析开销开始线性上升,尤其在低端安卓机上,HTML parser 吞吐量下降明显。Chrome DevTools 的 Parse HTML 阶段耗时会从 2ms 跳到 15ms+,直接卡住后续 Recalculate Style。
工具链不会自动截断——critters 提取的是“所有首屏用到的选择器”,如果设计师塞了个 800 行的 .rich-text 全局样式,它照单全收。
- 检查输出的
<style data-critters></style>内容,用gzip -c critical.css | wc -c测真实体积(HTTP/2 下按压缩后大小算) - 删掉注释、合并重复声明、移除未使用的伪类(如
:hover在首屏不可交互时可删) - 对 wangEditor5 这类富文本编辑器输出的内容,别把整套
prismjs主题 CSS 内联——只保留pre和code的基础盒模型,高亮逻辑交给 JS 动态加 class - 服务端渲染(SSR)场景下,内联后务必移除对应外链
<link>,否则样式重复应用,!important冲突都可能引发布局偏移
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











