【免费下载链接】beasties
A library to inline your app's critical CSS and lazy-load the rest.
关键 CSS(Critical CSS)直接决定网页首屏多快出现在用户眼前。beasties是一款专门做关键 CSS 内联与样式表懒加载的轻量级工具,它的核心特点是不依赖无头浏览器(Headless Browser)渲染页面,就能在构建或响应阶段极速提取关键 CSS 并内联进 HTML,是 SSR / 预渲染应用做首屏优化的理想选择。
先搞懂:什么是关键 CSS?它凭什么影响首屏
浏览器按 HTML 的顺序解析页面,而外部的<link rel="stylesheet">是一个同步阻塞资源——浏览器必须等 CSS 下载并解析完成,才会继续绘制页面。
这意味着:哪怕 HTML 50ms 就传完了,只要 CSS 卡了 800ms,用户看到的就是 800ms 的白屏。
关键 CSS就是渲染首屏内容所必需的那一小部分 CSS 规则。首屏优化的标准打法是:
- 把这部分 CSS内联到
<head>里,让浏览器拿到 HTML 就能立刻绘制; - 剩余的样式表通过preload 策略异步加载,不阻塞渲染;
- 内联过的规则从原样式表中移除,避免加载两份重复 CSS。
这套组合拳能显著改善 FCP(首次内容绘制)和 LCP(最大内容绘制)等核心指标。
传统痛点:为什么大多数方案要拖着无头浏览器
Critical、Penthouse 等经典工具的做法是:用 Puppeteer 启动一个完整的无头浏览器把页面渲染一遍,再提取"真正生效"的样式。
| 维度 | 无头浏览器方案 | beasties |
|---|---|---|
| 依赖 | 完整 Chromium,数百 MB | 无浏览器,极少依赖 |
| 速度 | 每页一次渲染,CI 里又慢又不稳 | 毫秒级处理单个文档 |
| 精度 | 能区分"折叠线以上"内容 | 内联文档实际用到的全部规则 |
| SSR 场景 | 每次响应都跑一遍不现实 | 天然适合逐请求处理 |
beasties 用"不感知视口"换来了极致的速度与轻量:它内联的是文档中所有被用到的 CSS 规则,而不仅是首屏那一点。对于样式规模合理的现代应用,这个取舍几乎无感。
为什么选 beasties:5 个硬核优势
beasties 是 GoogleChromeLabs/critters 的持续维护分支,能力上更进一步:
- ⚡快——不启动浏览器,依赖极少,可放心放进构建和 SSR 流程;
- 🔗生态集成——官方提供 Webpack 插件 beasties-webpack-plugin 和 Vite 插件 vite-plugin-beasties;
- 🔤字体优化——自动识别关键字体并 preload,还能把
@font-face规则内联(fonts: true); - 🧹智能裁剪——自动剪掉未使用的 keyframes 和 media query;
- ✂️去重瘦身——
pruneSource开启后,内联过的规则会从延迟加载的样式表里删掉。
核心逻辑分布在 packages/beasties/src/ 下:dom.ts 负责把 HTML 解析成轻量 DOM,selectors.ts 负责 CSS 选择器匹配,css.ts 负责样式规则处理。
beasties 是怎么在无浏览器下找到关键 CSS 的?
原理可以用四步说清:
- 把输入 HTML 解析成轻量 DOM 树(不是真浏览器,只是结构数据);
- 用 PostCSS 把 CSS 编译成规则树,默认启用
safeParser容错解析,老代码里的语法错误也不会炸; - 逐条评估选择器,找出文档中真实匹配的元素;
- 只把匹配到的规则内联进
<head>,原<link>标签则按你选的 preload 策略变成异步加载。
围绕这套机制,还有一批"手动挡"能力:
- 🏷️CSS 注释指令:在样式里写
/* beasties:include */或/* beasties:exclude */(支持 start/end 块标记),强制某条规则进或出关键 CSS,实现见 directives.ts; - 🎯
allowRules选项:程序化地按选择器或正则强制包含规则,适合"弹窗类样式必须内联"这类场景; - 🖥️
data-beasties-container:把首屏区域包一层,模拟视口。页面很大时能明显加快处理,也让内联更聚焦首屏; - ⏭️
data-beasties-skip:运行时动态替换的主题样式表可以整体跳过,保持标签原样。
三种快速上手路径:从安装到生效
路径 1:直接使用 beasties 库
npm i -D beastiesimport Beasties from 'beasties' const beasties = new Beasties() const html = ` <style> .red { color: red } .blue { color: blue } </style> <div class="blue">I'm Blue</div> ` const inlined = await beasties.process(html) // <style>.blue{color:blue}</style><div class="blue">I'm Blue</div>只被用到的.blue规则被保留并压缩,.red被丢弃。
路径 2:Vite 用户装 vite-plugin-beasties
在vite.config.ts里加一个插件,构建时自动处理index.html:
import { beasties } from 'vite-plugin-beasties' export default defineConfig({ plugins: [ beasties({ options: { preload: 'swap', pruneSource: true, // 从外部样式表移除已内联规则 inlineThreshold: 4000, // 小于 4KB 的样式表直接内联 }, }), ], })路径 3:webpack 用户装 beasties-webpack-plugin
const Beasties = require('beasties-webpack-plugin') module.exports = { plugins: [ new Beasties({ preload: 'swap', }) ] }插件源码分别在 packages/vite-plugin-beasties/src/ 和 packages/beasties-webpack-plugin/src/,两个插件共享同一套配置项。
进阶配置:让首屏优化再上一个台阶
选对 preload 策略
延迟加载样式表有 9 种策略,按"对浏览器的友好程度"排序大致如下:
| 策略 | 说明 | 需要 JS |
|---|---|---|
default | 样式表移到文档末尾,原位插入 preload 标签 | ❌ |
"body" | 所有样式表链接移到文档末尾 | ❌ |
"media"/"media-script" | media="not x"异步加载;后者用统一脚本恢复,兼容严格 CSP | ✅ |
"swap"/"swap-high"/"swap-low" | preload 占位、加载完成再换回 stylesheet | ✅ |
"js"/"js-lazy" | 注入类似 LoadCSS 的异步加载器 | ✅ |
false | 不添加 preload 标签 | ❌ |
需要 JS 的策略默认附带<noscript>兜底,关闭 JS 也不会丢样式。
高并发 SSR:compiler + runtime 双阶段模式
如果每个请求都完整解析 CSS,依赖约 1.8 MB、单文档要 3ms 起。beasties 提供了两阶段拆分:
- 构建期:compiler.ts 把样式表预编译成紧凑的"plan"(规则已压缩、选择器已归一化);
- 请求期:runtime.ts 零依赖、零 DOM,单遍扫描 HTML 直接拼接关键 CSS,413KB 大样式表场景下从 36ms 降到1.2ms。
plan 的编码与解码分别在 plan-encode.ts 和 plan-decode.ts,plan 结构定义在 plan.ts。
严格 CSP 环境的推荐姿势
onload内联属性会被严格 CSP 拦截,此时改用preload: 'media-script'并传入nonce——每份文档只输出一个内容固定的恢复脚本,也可以用静态 hash 放行。
字体与 keyframes 的精细控制
fonts: true:内联关键@font-face并 preload 关键字体,未用到的字族和unicode-range子集自动跳过;keyframes: 'critical'(默认)只内联被关键 CSS 引用的动画,'all'/'none'按需调整。
哪些项目最适合 beasties?
- ✅预渲染 / SSR 的单页应用——这是它的"主场",与 prerender-loader 类方案组合能大幅改善首屏绘制时间;
- ✅CI / 构建流水线——没有浏览器依赖,构建稳定不飘;
- ✅高并发 Node 服务端——compiler/runtime 模式下请求期零解析开销;
- ⚠️ 如果你的页面 CSS 极其臃肿,建议配合
data-beasties-container圈定首屏区域,或用注释指令剔除无关规则。
总结
一句话回顾:关键 CSS 内联 + 样式表懒加载 = 首屏提速的标准答案,而 beasties 用"不用无头浏览器"的设计把这个答案做到了毫秒级、零浏览器依赖、可无缝嵌入 Vite / webpack / SSR 全链路。对于想快速改善 FCP 与 LCP 又讨厌 CI 里拖着一坨 Chromium 的团队,它值得一试 🚀
【免费下载链接】beasties
A library to inline your app's critical CSS and lazy-load the rest.
相关推荐
VectorChord核心功能全解析:从RaBitQ压缩到分层K-means索引的技术奇迹
VectorChord核心功能全解析:从RaBitQ压缩到分层K means索引的技术奇迹 VectorChord作为PostgreSQL中可扩展、快速且磁盘友
javascript.info 网络专题:为什么跨域请求需要 Origin 头而不是只靠 Referer
javascript.info 网络专题:为什么跨域请求需要 Origin 头而不是只靠 Referer HTTP 的 Referer 头携带了发起请求的完整页
文档/教程前端为什么你的浏览器书签需要Neat Bookmarks来拯救?
为什么你的浏览器书签需要Neat Bookmarks来拯救? 在数字时代,浏览器书签堆积如山已成为每个互联网用户的共同困扰。面对杂乱无章的书签栏,你是否曾感到无
前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考