目录
使用 Oxlint + Oxfmt,可以将编码规范转化为自动检查,缩短 lint 和格式化时间。在 REALITY 报告的 Monorepo 迁移中,检查时间从 9.29 秒缩短至 2.95 秒,同时保留了导入分组和自定义的 Tailwind CSS 类排序。
要点#
- 根据仓库所用规则的覆盖情况和格式化差异选择工具。
- 对机械性规范使用格式化和安全的自动修复,对禁止的模式使用处理方法明确的 lint 错误。
- 将格式化、lint 修复和工具变更拆分为便于审查的提交。
- 审查自动修复,同时运行类型检查和测试后再合并。
根据兼容性选择#
REALITY 在一个基于 pnpm 工作区和 Turborepo 的 Monorepo 中验证了 Biome 和 Oxc,该仓库包含 React 应用和共享设计系统。由于存在通过 @theme 定义的 Tailwind CSS v4 工具类,类排序是一项重要要求。
Biome 基本复现了原有的基础格式,约 460 个文件中仅有 1 个发生变化。导入排序改变了 85 个文件,Tailwind 类排序改变了 71 个文件。在这次验证中,Biome 的类排序器未读取项目的样式表,导致自定义工具类的位置发生变化。
Oxfmt 无差异地复现了所验证的基础格式,也支持所需的导入分组和考虑样式表的 Tailwind 排序。这是特定仓库中的结果。无论选择哪种工具,都请验证以下 4 点。
- 代表性文件的格式化差异。
- 导入分组、空行和副作用导入。
cn()、cva()等辅助函数中的自定义 Tailwind 工具类。- 对当前依赖的所有 ESLint 规则的支持情况。
配置统一检查#
将 .oxlintrc.json 和 .oxfmtrc.json 放在仓库根目录。REALITY 将各包的 lint 和格式化任务替换为每个工具对整个仓库各运行一次的方式,并将工具的直接依赖从 14 个减少为 oxlint、oxfmt 和 oxlint-tsgolint 这 3 个。
报告中的脚本如下。
{
"scripts": {
"lint": "oxlint --type-aware --deny-warnings",
"format": "oxfmt",
"format:check": "oxfmt --check"
}
}配置 Oxfmt 的 sortImports,按需设置独立的 side_effect 分组等,以保留现有分组方式。对于 Tailwind 排序,在 sortTailwindcss.stylesheet 中指定设计系统的样式表,并纳入 cn、cva 等类名构建函数。请确认锁定的版本是否支持各项配置。
将规范落实到代码中#
对每项规范,采用能满足目的的最小执行手段。导入顺序和 Tailwind 类顺序交给格式化处理,导入限制交给 lint 规则处理。对于需要结合上下文判断的事项,例如何时使用函数声明而非箭头函数,应保留在文档中。
lint 错误应同时说明原因和替换方法。如果应用必须使用支持区域设置的导航封装,那么导入限制消息可以这样写:“请使用 @/i18n/navigation 中的 Link。直接从 next/link 导入将无法应用本应用的区域设置处理。”这样,开发者和编码智能体都能获得修复所需的信息。
明确例外,并限制其范围。如果禁止默认导出,应通过基于文件模式的覆盖配置,排除框架要求必须使用默认导出的文件。对于禁用的规则,用注释说明原因及启用条件。不要将规范强行套入不适合的规则。REALITY 因为某条限制函数书写形式的规则产生了 174 处超出预期范围的违规,最终没有采用该规则。
用 4 个提交完成迁移#
让迁移内容保持易于审查。
1. 保留现有工具,添加 Oxlint、Oxfmt 及其配置。 2. 在专门的提交中格式化整个仓库。 3. 在另一个提交中应用 lint 修复,按规则审查变更。 4. 切换脚本和 CI,删除不再需要的依赖和任务。
在 REALITY 的 lint 修复阶段,224 个文件改为使用 import type。将其与格式化分开后,更容易追踪变更目的。也请检查细节。导入排序最初删除了副作用导入后的空行,因此需要调整分组。
在可比较的条件下测量迁移后的配置。REALITY 对原有配置禁用了 Turborepo 缓存,预热 1 次后运行 5 次,取其中位数。总耗时分别为:ESLint + Prettier 9.29 秒、Biome 2.69 秒、Oxlint + Oxfmt 2.95 秒。每条命令都包含约 1.1 秒的 pnpm 启动时间,规则覆盖情况也有所不同,因此这些数值反映的是整个工作流,而非引擎本身的基准性能。
检查修复内容和规则覆盖情况#
自动修复可能改变语义。REALITY 报告称,类型导入和重复导入的修复相互干扰,导致必要的值导入被删除。另一项修复将 toHaveBeenCalled() 改为 toHaveBeenCalledWith(),把“被调用过”变成了“被无参数调用过”。类型检查无法检测到这一断言变化。请审查修复,并运行类型检查和测试。
逐项确认规则支持情况。在这次迁移中,由于没有同等规则,REALITY 移除了 eslint-plugin-turbo 的环境变量规则。此外,按类别启用规则时,在所验证的配置中,rules-of-hooks 仍处于禁用状态。请锁定工具版本,并在升级时审查格式化差异。即使兼容 Prettier,也不意味着所有场景下的输出都完全相同。
还需注意智能体频繁执行的钩子。删除未使用导入的修复,可能会在后续编辑添加使用位置之前就删掉导入。请在一次编辑中同时写入相关导入及其使用代码,或等变更完成后再运行修复。
下一步#
创建迁移分支,在仓库中运行候选工具,审查格式化差异和未支持的规则后,再修改 CI。
来源:https://zenn.dev/reality_tech/articles/oxc-monorepo-20261006
目录
