通过提供更多的CSS来提升网站性能
摘要
GitHub的Primer设计系统从CSS-in-JS迁移到CSS Modules后,服务器端渲染速度提升了55%,客户端样式计算时间减少了25%。
<p><a href="https://lobste.rs/s/fli8va/improving_site_performance_by_shipping">评论</a></p>
查看缓存全文
缓存时间: 2026/09/27 07:34
# 通过输出更多 CSS 提升网站性能
来源:https://github.blog/engineering/architecture-optimization/improving-site-performance-by-shipping-more-css/
Primer 设计系统 (https://primer.style/) 为当今 GitHub 上的众多体验提供支持。从按钮到横幅再到面包屑导航,这些基础组件需要在各种场景下确保可访问性、灵活性和高性能。
早在 2023 年,某些页面上的组件数量开始激增。这给我们的现有 CSS-in-JS 方案带来了一系列性能相关的挑战:
- 初始页面加载时间延长,因为样式需要在客户端初始化
- 随着样式收集从客户端转向服务器端,服务器端渲染性能下降
- 随着页面上组件数量的增加,样式更新变得难以控制
显然,Primer 团队需要从源头上解决这个问题。我们需要寻找一种替代方案,完全避免当前方案在客户端和服务器端带来的成本。最重要的是,任何我们选择的替代方案都必须以避免在迁移过程中破坏 GitHub 任何功能的方式运作。
## 引入 CSS (Modules)
Primer 团队找到了一个满足我们所有标准的解决方案:CSS Modules (https://github.com/css-modules/css-modules)。这种格式允许我们做最喜欢的事情之一:编写和使用原生 CSS 特性,同时仍然保留一些我们从 CSS-in-JS 中期望的共置和封装特性。
使用 CSS Modules 时,样式将与组件的 JavaScript 源代码一起编写在 CSS 文件中。它还允许我们将所有类名默认视为本地类名,从而防止全局选择器可能带来的一些冲突和挑战。这种格式还消除了对任何客户端或服务器端运行时行为的需求。相反,样式将被合并到 CSS 样式表中,作为页面 HTML 的一部分发送。
然而,这个方案与我们当时的 CSS-in-JS 方案截然不同。这一更改需要更新每个 Primer 组件和 GitHub 上使用此技术编写的每个组件。幸运的是,设计系统是大规模交付此类变更的绝佳载体。
## 向 CSS Modules 迈进的渐进式步伐
迁移到 CSS Modules 的情况已经明确。Primer 团队需要为其每个组件交付更新,将它们从 CSS-in-JS 迁移到 CSS Modules。同时,我们对这些组件所做的更新不能破坏 GitHub 中的任何使用方式。最后,我们用于 CSS-in-JS 的底层技术也必须继续为 GitHub 中当前使用它的所有组件工作。
在所有这些限制条件下,我们决定采用一种增量迁移策略,使我们能够在不破坏整个系统的安全前提下交付组件更新。对于每个组件,我们的计划是:
- 添加一个新文件,将现有样式转换为 CSS Modules 格式
- 将组件添加到一个特性标志中,该标志可在新旧样式之间切换
- 使用现有的视觉回归测试来验证 CSS-in-JS 方案和 CSS Modules 之间的快照是否完全相同
- 逐步向我们的团队,然后是 GitHub 员工,最后是所有 GitHub 用户推出此特性标志,以便沿途发现任何问题
这个过程创建了一个强大的反馈循环,随着 Primer 持续向 GitHub 交付这些更改,问题能在早期就被标记出来。特性标志的使用使我们能够安全地进行此迁移,同时清晰地了解 CSS Modules 带来的性能收益。
到 2024 年 12 月,Primer 中的所有组件都已通过此过程迁移至 CSS Modules。我们看到了全面的性能提升,特别是:
- 服务器端渲染页面的时间减少了 55%
- 页面上组件的初始化时间减少了 25%
在 Primer 中进行这项工作带来了明确的性能提升,我们开始思考,如果在 GitHub 的其他部分进行这些转换,是否也能看到类似的性能提升。同样,我们最终还需要多久才能在整个公司范围内停止支持 CSS-in-JS?
## 在 GitHub 上逐步弃用 CSS-in-JS
从 Primer 中移除 CSS-in-JS 方案最棘手的部分之一在于 `sx` 属性的使用。这个属性曾是样式化和定制 Primer 组件的*标准方式*。团队可以提供一个内联对象来定制组件的一切。它体现了 CSS-in-JS 的优点和缺点:
- 出色的 TypeScript 支持,并与我们的设计令牌集成
- 与组件共置,所有内容都在一处
- 由于用于 `sx` 的内联对象的动态特性,运行时开销很高
- 随着页面上使用 `sx` 的组件数量增加,扩展变得困难
因此,我们弃用 CSS-in-JS 旅程的第一部分是减少整个 GitHub 的 `sx` 使用。这将使我们能够立即提升性能,类似于迁移 Primer 组件时看到的收益。这也为我们完全从产品中移除 CSS-in-JS 做好了完美的准备。
## Primer 的双重性
需要注意的是,虽然设计系统本身已正式弃用 `styled-components`,但 GitHub 代码库的很大一部分并未如此。由于 `sx` 属性多年来一直是 GitHub 事实上的样式标准,我们需要迁移成千上万个 `sx` 属性,甚至才能考虑让 GitHub 转向简洁的、不依赖 `styled-components` 的新 `@primer/react` 版本。
那么...我们是如何在增加信心和降低风险的同时完成这项庞大工作的呢?答案是:不是一蹴而就的。
最初的 CSS 迁移比我们之前提到的更为细致:除了将组件迁移到 CSS 模块、在生产环境中进行特性标志测试和缓慢推出它们之外,我们还在一个过渡库 `@primer/styled-react` (https://github.com/primer/react/blob/main/packages/styled-react/README.md) 中创建了“包装”组件。这个包的全部目的是允许在新迁移的组件中使用 `sx`。这样,GitHub UI 代码库中使用此属性的实例可以通过从 `@primer/styled-react` 导入相同的组件继续使用它们,而我们则实现了从 `@primer/react` 直接导入的性能增益(针对不使用 `sx` 的情况)。
## Styled Box Zero
迁移过程的下一阶段如下:
- 逐个包进行:- 将所有 `sx` 用法转换为等效的 CSS 模块文件。这包括交叉参考(请参阅迁移到 CSS 变量 (https://primer.style/product/primitives/migrating/))- 将 `@primer/styled-react` 导入替换为 `@primer/react` 导入 - 在预生产环境中测试 - 部署
有趣的是,当我们准备着手这项庞大工作时,`styled-components` 宣布进入维护模式 (https://opencollective.com/styled-components/updates/thighank-you),这进一步证实了我们正朝着正确的方向前进。
工作于 2025 年 4 月启动,峰值时有约 7,760 个 `sx` 属性需要迁移;我们直到 2026 年 5 月才将其完成。最初,我们优秀的一位内部开发者 Ian Sanders (https://github.com/iansan5653) 创建了一个 VS Code 插件 (https://marketplace.visualstudio.com/items?itemName=ian-sanders.sx-to-css) 来协助逐属性迁移。内部还开发了一个类似的代码修改工具,并用于迁移 GitHub 代码库中的整个文件。这项工作虽然需要一些人工监督和仔细验证,但大部分是自动化的。8 名工程师轮换在 6 个月内迁移了 6,419 个属性,观察到服务器端渲染时间性能在部分页面提升了 1% 至 22%。
表格标题为“服务器端渲染”,带有搜索字段和列标题:CATALOG_SERVICE、CONTROLLER 和 IMPROVEMENT。列出了 GitHub 服务和控制器及其改进百分比,范围从 3.05% 到 21.97%,其中最高值为 github/code_view / commit 的 21.97%。在 GitHub 的另一面,Copilot 的能力正在呈指数级增长。人工智能变得更智能、更强大;在这项工作仍在进行时,我们发布了 Copilot 编程代理和 Copilot 代码审查。
当我们重新拾起这项工作时,已是 2026 年 4 月,情况已大不相同;我们仅用了三周时间,在两名工程师、不懈的决心和大量 Copilot 编程代理的帮助下,就将 `sx` 属性数量从 895 个减少到了 0。
区域图标题为“总 SX 属性”,显示数值从 5 月的约 7,300 下降到次年 6-7 月的接近零,其间有几次短暂的尖峰。两个高亮点分别标注为 8 月左右的 6.87k 和 10 月左右的 5.37k。## 主题之战
这是个大日子:我们终于完成了阻碍我们完全移除 `styled-components` 的 `sx` 迁移工作,这历经了数年时间...我们现在终于可以清理这些依赖项,并转向其他更令人兴奋的工作了,对吧?错!
GitHub 支持七种不同的主题 (https://docs.github.com/en/get-started/accessibility/managing-your-theme-settings),所有这些主题都提供高对比度模式变体。所有这一切,你猜对了,都是通过 `styled-components` 实现的。在我们甚至考虑移除这些依赖项之前,我们需要将我们的主题化方案解耦。
现在,这并不像听起来那么严重。我们的主题变量一直通过我们的 `@primer/css` 包在 CSS 中定义,并且我们在 2025 年底迁移 `@primer/react` 时,已经为非 styled 主题化做了前瞻性规划。我们需要移除的是由 `styled-components` 启用的 JavaScript 用法和实用工具。我们再次投入了工作。
你现在应该熟悉流程了:执行迁移,缓慢推出,所有内容都使用特性标志。两个月过去,期间遇到了一些小问题,我们已准备好进行依赖项移除;我们甚至为移除本身也设置了特性标志。安全总比后悔好。
## 结局圆满
自 2026 年 6 月起,GitHub 已完全运行在 CSS 模块上。我们建立的安全措施使我们能够安全地推出重大的架构变更,在生产环境中进行压力测试,捕获错误,高效地调整和修复,最终使我们能够实现目标,并在此过程中获得了显著的性能提升。
起初看似简单的 CSS 迁移,最终演变成 GitHub 大规模样式化、主题化和交付用户界面的方式的渐进式平台重塑。到结束时,我们不仅从 dotcom 中移除了 `sx`、`styled-components` 和 `styled-system`,而且在整个过程中没有破坏 GitHub。增强我们产品的性能、用户体验和愉悦感,始终是我们 GitHub 这里所有人的首要关注点。
---
## 标签:
- 自动化 (https://github.blog/tag/automation/)
- CSS (https://github.blog/tag/css/)
- 设计系统 (https://github.blog/tag/design-systems/)
- 性能工程 (https://github.blog/tag/performance-engineering/)
- Primer (https://github.blog/tag/primer/)
- 脚本 (https://github.blog/tag/scripting/)
## 作者
Josh Black
Josh Black 是一位常驻德克萨斯州奥斯汀的软件工程师。他热爱从事设计系统工作,创造无障碍体验,并享用玉米片配菜(chilaquiles)。
Marie Lucca
Marie 是位于亚特兰大的 GitHub Primer 软件工程师。如果不调整像素,她可能正在将随身行李推入大西洋上空的某个头顶行李舱。
## 探索更多 GitHub 内容
文档
### 文档
精通 GitHub 所需的一切,尽在此处。
前往文档 (https://docs.github.com/)
GitHub
### GitHub
在 GitHub 上构建未来,这里是从任何地方构建任何东西的地方。
开始构建 (https://github.com/)
客户故事
### 客户故事
认识使用 GitHub 构建产品的公司和工程团队。
了解更多 (https://github.com/customer-stories)
GitHub Universe 2026
### GitHub Universe 2026
于 10 月 28-29 日在旧金山或线上加入我们,参加我们的旗舰开发者活动 GitHub Universe,汇聚人员、代理和全球代码。
立即注册 (https://githubuniverse.com/?utm_source=Blog&utm_medium=GitHub&utm_campaign=module_uni_26)
相似文章
CSS-in-JS 竞技场:Bamboo、StyleX 和 Panda 在像素相同应用上的比较
本文介绍了用于编译时 CSS-in-JS 引擎的基准测试框架,在像素相同的 React 应用上比较了 Bamboo、StyleX 和 Panda CSS,其中 Bamboo 在交付字节数和构建时间等性能指标上领先。
CSS Zen Garden梦想,终于发布
本文详细描述了使用现代、原生CSS(无需预处理器)重建Firefox.com的过程,展示了从CSS Zen Garden概念到实用、生产就绪的Web开发的演进。
CSS压缩是否必要?(2023年)
本文评估了CSS压缩是否对网页性能有必要,基于测试和实际分析,得出其收益微乎其微的结论。
告别Tailwind,学习组织CSS
作者反思了从Tailwind CSS迁移到带语义HTML的原生CSS的过程,分享了利用从Tailwind学到的重置、组件和工具类等系统来组织CSS的心得。
渐进式 Web Components
Ariel Salminen 介绍了 Elena,一个 2.6kB 的开源库,用于构建渐进式 Web Components,这些组件无需 JavaScript 即可渲染 HTML 和 CSS,并逐步增强。文章解释了该方法背后的设计理念和分类法。