CSS-in-JS 竞技场:Bamboo、StyleX 和 Panda 在像素相同应用上的比较
摘要
本文介绍了用于编译时 CSS-in-JS 引擎的基准测试框架,在像素相同的 React 应用上比较了 Bamboo、StyleX 和 Panda CSS,其中 Bamboo 在交付字节数和构建时间等性能指标上领先。
查看缓存全文
缓存时间: 2026/08/18 16:21
gajus/css-in-js-arena 来源:https://github.com/gajus/css-in-js-arena
CSS-in-JS 竞技场
一个为编译时 CSS 引擎设计的性能测试工具。
每个引擎在 apps/ 目录下拥有自己的 React Router 8 应用,且每个应用都渲染相同的六页管理控制台——相同的标记、相同的设计、相同的数据。
在进行任何测量之前,所有应用都经过验证确保像素级一致,因此测试数据仅反映引擎本身的差异,不受其他因素影响。
| 引擎 | 集成方式 | 版本 |
|---|---|---|
| Bamboo CSS (https://bamboocss.com) | @bamboocss/vite | 1.45.3 |
| StyleX (https://stylexjs.com) | @stylexjs/unplugin | 0.19.0 |
| Panda CSS (https://panda-css.com) | @pandacss/postcss | 1.12.0 |
测量于 2026-08-18,使用上述版本 · macOS,Node 24.10,Vite 8.2.1
| 引擎 | 输出字节数 | 构建与开发 | 编写体验 | 正确性与可维护性 | 胜出项数量 🏆 |
|---|---|---|---|---|---|
| Bamboo 🏆 | 8 / 10 🏆 | 3 / 6 🏆 | 7 / 8 🏆 | 4 / 4 🏆 | 22 / 28 🏆 |
| StyleX | 3 / 10 | 1 / 6 | 2 / 8 | 1 / 4 | 7 / 28 |
| Panda | 2 / 10 | 2 / 6 | 6 / 8 | 1 / 4 | 11 / 28 |
每个类别中的胜出项数量(基于各类别中计分项)。它们权重不同且有两项未计分,因此统计结果仅作为快速参考,而非最终判断——且字节数的差异无法在规模扩大时维持,如下一节所示。
主表格未涵盖之处
以上所有数据都基于单一应用在单一配置下的结果。两个因素会改变结论:应用拥有的样式数量,以及是否仅使用明暗主题。
样式数量
主表格描述的是一个包含 549 条规则块的应用。真实应用数量会高出一个数量级,此时固定开销不再重要,每条规则的边际成本成为关键。
tools/scale.mjs 生成 N 个具有完全不同值的样式定义,并测量输出的样式表,以隔离每个引擎的每条规则真实成本。
下载的样式表,brotli 压缩,相对于 Bamboo:
| 样式定义数量 | Bamboo | StyleX | Panda |
|---|---|---|---|
| 0 — 应用原样输出 | 参考 | +3.0% | +39.9% |
| 50 | 参考 | +18.0% | +35.4% |
| 200 | 参考 | +50.2% | +28.0% |
| 800 | 参考 | +102.9% | +16.3% |
两位挑战者都发生了变化,但方向相反。 在竞技场规模下的排名,并不等同于生产规模下的排名。
| 与 Bamboo 在 n=0 时的差距 | 在 n=800 时 | |
|---|---|---|
| Bamboo | 40.3 B 原始 · 2.0 B brotli | 参考 |
| Panda | 40.3 B 原始 · 2.0 B brotli | +16,903 B |
| StyleX | 65.8 B 原始 · 5.5 B brotli | +4,222 B |
Panda 的边际成本与 Bamboo 完全相同,精确到字节。 它的全部开销是固定的 16,903 B 脚手架——在 0 个样式和 800 个样式时都相同——因此“Panda 输出的 CSS 多 40%“只是针对小应用而言,并非描述 Panda 本身。
StyleX 则相反:几乎是纯斜率,在相同范围内增长了 30 倍,因为每条规则都带有 :not(#\#) 特异性填充,每个声明都会重复且压缩效果不佳。
主题
品牌主题与明暗主题是不同的问题,而竞技场应用不包含任何品牌主题——因此需要单独测量。
tools/theming.mjs 通过每个引擎自己的多主题 API(Bamboo theme.variants,Panda themes,StyleX createTheme)注入 N 个主题,每个主题使用明暗两个值覆盖相同的 18 种颜色。
浏览器下载的样式表,brotli 压缩:
| 品牌主题数量 | Bamboo | StyleX | Panda |
|---|---|---|---|
| 0 | 6,802 B | 7,008 B | 9,518 B |
| 2 | 6,802 B | 7,427 B | 9,518 B |
| 8 | 6,802 B | 8,350 B | 9,518 B |
| 每个主题增加 | 0 B 🏆 | +168 B | 0 B 🏆 |
主题载荷,仅在选择主题时获取:
| 维度 | Bamboo | StyleX | Panda | 差距 |
|---|---|---|---|---|
| 每个主题字节数 | 1,374 B 🏆 | 不适用——在样式表中 | 2,805 B | −51% |
| 关键路径中的主题 | 无 🏆 | 全部 | 无 🏆 | StyleX 无延迟选项 |
这是两种机制,而非三种。Bamboo 和 Panda 将每个主题作为独立工件输出,按需导入,因此无论有多少主题,首次加载大小都保持不变。
StyleX 的 createTheme 会编译到链接的样式表中,因此每个访问者都要为所有主题付费——在八个主题时,其 CSS 比零主题时大了 19%。
在两个延迟加载的引擎之间,差距与明暗主题行中的编码差异相同:Bamboo 编写 base 和 _osDark,让 light-dark() 解析其余部分;Panda 编写四个值。这相当于每个主题的字节数是前者的 2.04 倍。
对于只发布一个固定品牌主题且从不切换的网站,情况则相反:此时延迟工件会带来额外的请求,而样式表本身本已包含这些字节。
复现方法
此处的所有数据均来自单台机器上的一次连续测量会话。测试工具、一致性检查以及具体命令位于 RUNNING.md。
常见问题
为什么禁用了 CSS 压缩?
三个应用中均设置了 build.cssMinify: false。Vite 的默认设置会在输出样式表上运行 Lightning CSS 并重写它——最明显的是将 light-dark() 降级为 baseline-widely-available 目标下的 54 个变量 polyfill。这测量的是降级工具而非引擎,并且只惩罚输出现代 CSS 的引擎。关闭后,此处测量的每个样式表都是其引擎输出的原始内容。
StyleX 仍然显示一些 Lightning CSS 输出,因为 @stylexjs/unplugin 直接依赖它——这是其产品的一部分,而非测试工具的问题。
相似文章
ReactBench v1(14分钟阅读)
ReactBench是一个新的评估基准,用于测试编码代理在实际React工作中的表现,它超越了简单的测试通过,通过开源React Doctor验证器强制执行React的性能、可访问性和质量。早期结果显示,顶级模型解决的任务不到一半,其中新引入的问题中最常见的是bug。
@GoSailGlobal: https://x.com/GoSailGlobal/status/2052573500800700560
SWE-WebDev Bench 是 arXiv 上的一篇论文,评测了 6 个主流 vibe coding 平台(Lovable、Replit Agent3、Vercel v0-Max、Base44、Emergent E1-OPUS、QwikBuild),发现所有平台工程综合分都没超过 60%,前端 UI 漂亮但后端、安全、生产就绪度集体翻车,需要 12-60 小时人工修复才能上线。
Show HN:一个CSS 3D引擎(无需WebGL)
PolyCSS 是一个 CSS 多边形网格库,能将 3D 模型渲染为真实的 HTML 元素(使用 CSS matrix3d),支持 OBJ/MTL、GLB 和 VOX 格式,可与 React、Vue 或原生 JavaScript 配合使用。
CSS-DOS — 用CSS构建的计算机
一个创意项目,完全使用CSS构建类似DOS的计算机界面,展示了现代前端样式的强大功能。
Bonsai:Janestreet 的 UI 库
Bonsai 是 Jane Street 的开源 UI 库,用于在 OCaml 中构建响应式 Web 应用程序,具有可组合状态、增量渲染和模板语言等特点。