返回 AI 情报
技巧精选 642026-09-25 23:00Josh BlackGitHub Blog

GitHub 如何通过迁移 CSS Modules 将 SSR 时间降低 55%

Improving site performance by shipping more CSS

精选理由

原文给出大厂从 CSS-in-JS 迁移到 CSS Modules 的完整路径和量化收益,可迁移到类似的前端架构改造。

AI 摘要

GitHub 工程师 Josh Black 复盘将 Primer 设计系统从 CSS-in-JS 迁移到 CSS Modules 的历程。截至 2024 年 12 月 Primer 全部组件迁移完成,服务端渲染时间减少 55%,组件初始化时间减少 25%。

正文 · AI 翻译

Primer Design System 支撑着如今你在 GitHub 上看到的许多体验。从按钮到横幅再到面包屑导航,这些基础组件必须在各种场景下都具备可访问性、灵活性和高性能。

早在 2023 年,某些页面上的组件数量开始激增。这给我们现有的 CSS-in-JS 方案带来了若干与性能相关的挑战:

由于样式在客户端初始化,初始页面加载耗时更长

随着样式收集从客户端转移,服务端渲染性能下降

随着页面上组件数量的增长,样式更新逐渐失控

很明显,Primer 团队需要从根源上解决这个问题。我们需要找到一种替代方案,彻底避免当前方案所面临的客户端和服务端开销。最重要的是,我们选择的任何替代方案都必须以在迁移期间不会对 GitHub 造成任何破坏的方式运作。

引入 CSS(Modules)

Primer 团队找到了一个满足我们所有标准的解决方案: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 prop 的使用。这个 prop 曾是为 Primer 组件设置样式和进行自定义的方式。团队可以提供一个内联对象来自定义组件的方方面面。它代表了 CSS-in-JS 最好的一面,也代表了最糟的一面:

出色的 TypeScript 支持,并与我们的 Design Tokens 集成

与组件同处一地,因此一切都集中在一个地方

由于用于 sx 的内联对象具有动态特性,运行时开销很高

随着页面上使用 sx 的组件数量增长,扩展变得困难

因此,我们摆脱 CSS-in-JS 之旅的第一步,就是减少 sx 在 GitHub 各处的使用。这让我们能够立即提升性能,效果类似于我们迁移 Primer 组件时所获得的收益。它也为我们从产品中彻底移除 CSS-in-JS 做好了完美铺垫。

Primer 的双重性

需要注意的是,虽然设计系统本身已正式停用,styled-components但 GitHub 代码库本身的大部分内容却并非如此。由于sxprops 多年来一直是 GitHub 事实上的样式标准,我们面临着数千个sxprops 需要迁移,之后才能考虑将 GitHub 迁移到这套简洁全新的@primer/react版本上,而该版本不再依赖styled-components.

那么……我们是如何在完成如此庞大工作量的同时,还提升了信心并降低了风险?答案是:并非一蹴而就。

最初的 CSS 迁移比我们对外透露的要更微妙一些:除了将组件迁移到 CSS modules、通过功能开关在生产环境中测试并逐步灰度发布之外,我们还在一个名为 @primer/styled-react 的传递性库中创建了“包装”组件。这个包的整个目的,是让 sx 的用法能够进入新迁移的组件中。这样一来,GitHub UI 代码库中使用该 prop 的实例,可以通过 @primer/styled-react 导入同一个组件来继续使用它们,与此同时,对于那些不需要该 prop 的场景,我们则通过直接从 @primer/react 导入获得了性能收益。

Styled Box Zero

迁移过程的下一阶段如下:

On a package-by-package basis:

将所有 sx 用法翻译为等效的 CSS modules 文件。这包括交叉引用(参见 迁移到 CSS 变量)

将 @primer/styled-react 导入替换为 @primer/react 导入

在预生产环境中测试

部署

说来也巧,就在我们准备着手这项浩大工程之际,styled-components 维护模式 被宣布了,这进一步印证了我们正朝着正确的方向迈进。

这项工作于 2025 年 4 月启动,待迁移的 sxprops 峰值约为 7,760 个;直到 2026 年 5 月我们才看到它最终落地。起初,我们内部一位出色的开发者 Ian Sanders 创建了一个 VS Code 插件,用于辅助逐个 prop 的迁移。我们还在内部开发了一个类似的 codemod,并用它来迁移 GitHub 代码库中的整个文件。这项工作虽然需要一些人工监督和仔细验证,但大部分是自动化的。8 名工程师轮班工作,在 6 个月的时间里迁移了 6,419 个 props,观察到服务端渲染时间性能提升幅度从 1% 到某些页面的 22% 不等。

在 GitHub 的另一侧,Copilot 的能力正呈指数级增长。AI 变得越来越聪明、越来越强大;在这项工作仍在进行期间,我们发布了 Copilot coding agent 和 Copilot code review。

等到我们重新拾起这项工作时,已经是 2026 年 4 月,局面已大不相同;我们得以在三周内将 sxprops 从 895 个降到 0 个,靠的是一名工程师组成的团队、不屈不挠的决心,以及大量 Copilot 编程智能体。

主题之争

这是个大日子:我们终于完成了sx那些横亘在我们与彻底styled-components移除之间的迁移工作,历经数年之久……我们终于可以清理掉这些依赖,转向其他更令人兴奋的工作了,对吧?错!

GitHub 支持七种不同的主题,它们全都提供高对比度模式变体。而这一切的实现,靠的正是你猜到的那个东西——styled-components。在我们考虑移除这些依赖之前,首先需要把主题系统解耦。

现在,这件事并没有听起来那么严重。我们的主题变量一直是通过 @primer/css 包在 CSS 中定义的,而且我们在 2025 年底迁移 @primer/react 时就已经为非样式化的主题化做了前瞻性规划。我们需要移除的是由 styled-components 启用的 JavaScript 用法和工具函数。于是,我们又一次投入了工作。

到这一步你应该已经熟悉套路了:执行迁移、逐步推出、为一切加上功能开关。两个月后,期间经历了一些小波折,我们终于可以全面移除依赖了;我们甚至为此也加了功能开关。小心驶得万年船。

结局好,一切都好

截至 2026 年 6 月,GitHub 已 100% 运行在 CSS modules 之上。我们设置的各项防护措施使我们能够安全地推出重大架构变更、在生产环境中进行压力测试、高效地捕获错误、调整方向并修复问题,最终让我们成功达成目标,并在此过程中实现了显著的性能提升。

起初看似一次 CSS 迁移的工作,最终演变为对 GitHub 如何大规模地设计样式、应用主题和交付 UI 的一次渐进式重新平台化。到最终,我们不仅从 dotcom 中移除了 sx、styled-components 和 styled-system,而且在整个过程中没有让 GitHub 出现故障。提升产品的性能、用户体验和愉悦感,始终是 GitHub 全体成员最关注的事情。

原文

Original Title

Improving site performance by shipping more CSS

Source

GitHub Blog

Site

github.blog

Author

Josh Black

Published

2026-09-25 23:00

阅读原文· github.blog

继续阅读

GitHub 如何通过迁移 CSS Modules 将 SSR 时间降低 55% - AI 情报频道 - 小黑丸