‹ 目录
#前端#工程化

工程化学习

发表于 2026 年 9 月 15 日

之前我对工程化这三个字的理解比较浅显。我以为工程化就是电脑里装了个 Node.js,项目里有个 package.json,平时跑跑 dev 命令,写完敲一句 build 把生成的产物丢给服务器部署完事。至于网上大厂面试总喜欢聊的代码审查、矩阵测试、自动化发版,我一直觉得离自己平时的开发挺远的。有的就算了解了也没咋用过。

直到今天凌晨,我给 weapp-tailwindcss 提了个 PR。代码刚推上 GitHub 的那一瞬间,整个页面的检查区域弹出了 180 多个云端虚拟机测试任务。

云端的虚拟机在 Mac、Linux、Windows 上同时开工,满屏的任务跑了一个小时都没跑完。顺着今天被震住的思路,我想起朋友平时在维护的一个开源项目 gitlab-ui-react。以前只知道他在写个组件库,今天我带着刚学到的工程视角把他仓库的配置彻底看了一遍,才发现他把项目的工程底座搭得非常专业。

把这两天搞懂的这些工程化机制整理下来。

为什么提个 PR 要跑 180 多个虚拟机任务

刚提完 PR 那会,我有点疑惑。平时写的都是 JavaScript 和 TypeScript,Node.js 又是跨平台的,为什么要把代码扔到三个不同的操作系统上各跑一遍。

去翻测试日志才发现,前端编译在不同操作系统底层的坑很多。

第一个坑是 Windows 的文件路径反斜杠。在 Mac 和 Linux 上,文件路径是正斜杠,写成 src/components/Button.tsx。在 Windows 上,系统原生路径是反斜杠,写成 src\components\Button.tsx,前面还带着盘符。如果工具库作者在代码里写了带正斜杠的正则表达式去匹配文件路径,这行代码在 Mac 和 Linux 上正常运行,一到 Windows 上正则就匹配不中,整份文件直接被跳过,打包出来的样式会全部丢失。

第二个坑是换行符偏移。在 Windows 上敲回车,文件里存的是回车加换行,比 Mac 和 Linux 多了一个字节。很多前端代码转换工具按字符下标切片替换源码,在 Windows 上因为每一行都多了一个字符,切片位置整体往后移动,很容易切偏,甚至把双引号切掉报语法错误。

第三个坑是底层的机器码。现在很多构建工具底层用 Rust 或者 C++ 预先编译好的二进制程序。在 Mac 上跑的是苹果平台的二进制,在 Linux 上依赖特定版本的 C 运行库,在 Windows 上需要微软的动态链接库。只要依赖包挑错了,在某一台系统上装包就会当场崩溃。

加上这个项目要兼容 Taro、Uni-app、Mpx、Gulp 等几十个不同框架的打包生态,维护者不可能在自己的电脑上把 30 多个 demo 一个个手工跑一遍。

他在 .github/workflows/ 目录里写了配置,告诉 GitHub 只要有人提 PR,就向云端申请机器,把这 30 多个真实的小程序 demo 在 Ubuntu、Mac、Windows 上全量执行一次编译。只要任何一个 demo 编译失败,或者生成的样式产物跟官方保存的标准快照差了一个字符,系统就会给这个提交打上红叉。

机器流水线替很多人提前把这些系统兼容性问题排查掉了。

自动化发版机制

在这个项目里见识到的第二点是发版流程。以前我以为发 npm 包,就是作者在本地改改 package.json 里的版本号,然后在终端里执行发布命令。

而这个项目依靠机器人接管。提 PR 的时候,我在 .changeset/ 目录下建了个文件,勾选受影响的包,写了一段改动说明。

PR 合并之后,GitHub 上立刻自动冒出来一个由机器人发起的新 PR # 1201,标题叫 version packages。机器人自动把相关子包的版本号加了一位,把改动说明追加到全仓的更新日志里。维护者确认合并之后,云端脚本自动执行发布,新版本很快就推向了镜像源。整个过程不需要手动修改版本号。

回头看朋友的项目

带着这套刚学来的思路,我去看朋友的项目 gitlab-ui-react。

他之前跟我说他在把 GitLab 官方由 Vue 写的 UI 库用 React 重写一遍。我当时只觉得这个工作量很大。今天用工程化的角度去看,才发现他的项目搭得很有讲究。

我当时就震惊瘫坐。这么好的项目怎么不早点告诉我?

看他的 CI 配置,他只开了一台 Ubuntu 虚拟机。因为这是一个纯粹在浏览器里跑的组件库,不涉及操作系统底层的文件路径拦截,不需要去测 Windows 的反斜杠。他在云端只跑两件事,第一件事是严格的 TypeScript 类型检查,第二件事是在机器上装好 Chromium 内核,拉起 Playwright 真实浏览器去跑组件的交互测试。这样既能测出组件在浏览器里的表现,又不用让每次提交排队等十几分钟,选型很克制。

再看他的 package.json,用的是 React 19、TypeScript 7、Storybook 10 和 Vite 8。这些都是很新的版本,依赖关系能跑通需要不少排错工夫。

他的代码检查没有用老牌的 ESLint,而是在根目录放了个 .oxlintrc.json,跑的是 Oxlint。ESLint 本身是用 JavaScript 写的,项目一大跑起来就慢。Oxlint 是用 Rust 重写的工具,执行速度快了很多,跑一次检查只要几百毫秒。

他的仓库里同样配齐了发版配置和自动发布脚本,还写了定时任务去自动比对 GitLab 官方的最新设计变量。

感想

今天经历的这些事情让我的视角开阔了很多。

现在看一个项目,会注意它的工作流里有没有自动化、代码检查工具是不是新一代、测试有没有覆盖真实交互、发版是不是由脚本接管。

偶尔跟weapp-tailwindcss的维护者交流,他告诉我这些都是自己学的,公司是根据你的技能付钱,而不是你在公司学到了什么,公司考察你给你加钱。

写业务功能决定了功能能不能跑起来,工程化底座决定了这个项目在面对不同环境和多个人协作时能不能保持稳定。看懂了这些东西,后面自己做项目也多了一些参考。