- 开发工具
- Lint
- 代码质量
【免费下载链接】commitlint
📓 Lint commit messages
导读
@commitlint/config-lerna-scopes是 commitlint 官方提供的共享配置包,用于在 Lerna monorepo 中把scope-enum规则的值自动绑定为仓库内所有 package 的名称,从而保证提交信息的 scope 一定是真实存在的包名。本文以该包的 CHANGELOG 为主线,结合仓库内源码、测试与 fixtures,完整还原它的工作机制、历代 Lerna 版本兼容策略、Node 版本与模块体系的变更,以及官方推荐的迁移路径,读完即可在自己的 Lerna 仓库中直接启用并对升级影响心中有数。
一、这个配置包解决什么问题
在一个典型的 Lerna monorepo 中,改动通常发生在某个子包内,提交信息需要写清楚改动属于哪个包。手动维护一份 scope 枚举列表既不实时、也容易漏包,而本包的做法是:运行时动态扫描仓库,把所有 package 名作为scope-enum的合法取值。
从当前实现(index.js)看,该配置包只导出一个对象:
export default { utils: { getProjects }, rules: { "scope-enum": (ctx) => getProjects(ctx).then((packages) => [2, "always", packages]), }, };scope-enum规则以三元组[severity, modifier, value]形式返回:严重级别2(error)、修饰符always(必须匹配)、取值packages(动态计算出的包名数组)。测试index.test.js分别断言了这三项,例如expect(severity).toBe(2)与expect(modifier).toBe("always"),并验证该规则在缺少 context 时也不会抛错。
包名提取逻辑(index.js)还有一个细节:scoped 包名(@scope/pkg)会被去掉 scope 前缀,只保留短名。也就是说,名为@myorg/ui-kit的包,合法 scope 是ui-kit:
name.charAt(0) === "@" ? name.split("/")[1] : name二、在 Lerna 仓库中启用
2.1 安装
该包在package.json中声明了peerDependencies为lerna(且标记为optional,见 package.json),这意味着即使仓库里没有安装 Lerna 也不会阻塞安装,只是动态扫描需要lerna.json与实际的包目录存在。以 npm 为例:
npm install --save-dev @commitlint/cli @commitlint/config-lerna-scopes2.2 配置
在commitlint.config.js中直接extends该配置:
export default { extends: ["@commitlint/config-lerna-scopes"], };commitlint 会加载该包导出的规则,用仓库内真实的包名动态校验提交信息的scope。合法提交示例:
feat(ui-kit): add new button variant fix(api): correct timeout handling2.3 底层扫描流程
getProjects(index.js)的执行路径如下:
- 读取
context.cwd(默认process.cwd()); - 尝试调用
@commitlint/config-workspace-scopes的getPackages检测 npm/yarn workspaces; - 若检测到原生 workspaces,则直接使用 workspace 包名并打印弃用警告(详见下文迁移章节);
- 否则读取
lerna.json的packages声明,将每个 glob 模式归一化为指向package.json的 glob(normalizePatterns,index.js); - 用 Node 的
fs.promises.glob递归匹配(同时排除node_modules与bower_components),读取并解析所有package.json,最终提取包名并排序。
仓库内 fixtures 覆盖了多种形态:basic(packages/*)、nested(嵌套两级目录)、modules(混合普通包与命名空间目录)、scoped(@packages/**)、empty与no-packages-declaration(无packages声明)。对应的测试断言了每种形态的预期结果,例如嵌套仓库返回["nested-a", "nested-b", "nested-c"](index.test.js),scoped 仓库返回["scoped-a", "scoped-b"](index.test.js)。当lerna.json中没有packages声明时返回空数组(index.js),对应测试为work with no declared packages。
三、从 CHANGELOG 看版本演进与兼容策略
CHANGELOG 完整记录了该包从 v3.0.0(2017-07-10)到 v21.2.0(2026-06-30)的变更,以下是关键节点:
3.1 Lerna 版本支持路线
| 版本节点 | 变更内容 | 说明 |
|---|---|---|
| v3.0.x(2017-07) | 支持非标准 Lerna 仓库(support non-standard lerna repos) | 最早的动态包名扫描能力 |
| v4.1.1(2017-10) | 修复新版 Lerna 的包列表获取(fix package list get with recent lerna versions) | 紧跟 Lerna API 变化 |
| v9.0.0(2020-05) | 修正lerna在peerDependencies中的声明 | 依赖关系规范化 |
| v11.0.0(2020-09) | 移除对 Lerna v2 的支持(BREAKING CHANGES) | 进入 Lerna v3+ 时代 |
| v12.1.0(2021-03) | 继续支持 Lerna v3 | 兼容策略保持 |
| v15.0.0(2021-11) | 升级到 Lerna v4(BREAKING CHANGES) | 测试改用 npm bootstrap 简化 |
| v19.7.0(2025-01) | 支持 Lerna 7 和 8 | 兼容最新 Lerna 主版本 |
3.2 工作区(workspaces)支持与转向
v12.0.0(2021-01)新增了对 yarn workspaces 的支持。从当前源码看,这一能力仍然保留但已被标记为过渡性:getProjects会先探测 npm/yarn 原生 workspaces,命中时直接返回 workspace 包名,并输出三行警告:
It seems that you are using npm/yarn workspaces instead of lernas "packages" declaration. Support for workspaces will be removed in a future major version of this package. Please make sure to transition to "@commitlint/config-workspace-scopes" in the near future.测试index.test.js用fixtures/transition-to-workspace-scopes(该 fixture 的 package.json 声明了"workspaces": ["./packages/*"])验证了警告输出与返回值["workspace-package"]。
3.3 模块体系与运行时要求
- v13.0.0(2021-05):最低 Node 版本提升到 12;
- v17.0.0(2022-05):最低 Node 版本提升到 14,移除 Node 12 支持;
- v18.0.0(2023-10):最低 Node 版本提升到 18,移除 Node 14/16 支持;
- v19.0.0(2024-02):迁移到纯 ESM(BREAKING CHANGES),测试框架从 Jest 迁移到 vitest;当前 package.json 中
"type": "module"即为该变更的落地; - v21.0.0(2026-05):最低 Node 版本提升到v22,移除 Node 18/20 支持;当前 package.json 中
"engines": { "node": ">=22.12.0" }即为该变更的落地。
3.4 依赖与健壮性修复
- v19.8.0(2025-03):移除已废弃的
@lerna/project依赖(#4284),并用node:前缀引用内置模块以绕过require.cache调用(#4302);当前源码第 1-3 行的node:path、node:fs/promises导入即是这一演进的体现; - v12.1.1(2021-04):忽略没有
name字段的包(ignore packages without names);这与源码中if (name)的判断完全对应(index.js); - v17.6.2(2023-05):修复 Lerna
package.json的解析(lerna package.json resolution); - v17.6.3(2023-05):补充缺失依赖;
- 多个版本(v9.0.0、v16.2.4、v18.6.1 等)持续更新
semver依赖。
四、关键源码实现细节
4.1 glob 模式归一化
lerna.json中的packages通常写作packages/*、@packages/**或带package.json结尾的形式。normalizePatterns用正则pattern.replace(/\/?$/, "/package.json")保证每个模式最终都指向package.json(index.js),例如:
packages/*→packages/*/package.json@packages/**→@packages/**/package.json
4.2 去重与排序
由于不同 glob 模式可能重叠命中同一package.json,源码用Array.from(new Set(...))去重,最终结果经.sort()排序输出([index.js](https://link.gitcode.com/i/c70cbd00d89685676af34d7577353faf#L53-L59, L92)),保证规则取值稳定、可预期,也方便 diff 审查。
4.3 context 注入
scope-enum规则接收 commitlint 传入的 lint context,getProjects从中读取cwd(index.js)。这意味着该配置同样适用于 CI 或非标准目录结构:只要把 context 的cwd指向仓库根目录,就能在任意位置触发正确的包名扫描。测试通过fn({ cwd })传入各 fixture 目录验证了这一点。
五、迁移到 @commitlint/config-workspace-scopes
对于使用 npm/yarn 原生 workspaces 而非 Lernapackages声明的仓库,官方明确建议转向独立的@commitlint/config-workspace-scopes。两个包的机制几乎一致:都通过utils.getPackages扫描package.json并返回[2, "always", packages]形式的规则;区别在于前者读取lerna.json的packages,后者读取根package.json的workspaces字段(index.js),且后者会用node:前缀与globSync实现同步扫描,并自动过滤无name的包(index.js)。
迁移只需两步:
npm install --save-dev @commitlint/config-workspace-scopesexport default { extends: ["@commitlint/config-workspace-scopes"], };迁移前请确认根package.json的workspaces字段确实存在且格式正确(必须是非空数组),否则getPackages会直接返回空数组(index.js),导致scope-enum无任何合法取值。
六、升级前需要知道的事
结合 CHANGELOG 中的 BREAKING CHANGES,升级到当前 v21.x 系列时重点检查:
- Node 版本:当前版本要求
node >= 22.12.0,Node 18/20 已不再支持(v21.0.0 起); - 模块体系:包已是纯 ESM(
"type": "module"),require()引入将不再可用,配置文件需使用 ESM 语法; - Lerna 版本:本包面向 Lerna v4 及更新版本(v19.7.0 起支持 v7/v8),若仍停留在 Lerna v2 需先升级 Lerna;
- workspaces 用户:若仓库实际使用 npm/yarn workspaces,运行时会出现过渡警告,且未来主版本将移除该能力,建议尽快迁移到
@commitlint/config-workspace-scopes; - scope 命名规则:scoped 包只取短名(
@myorg/pkg→pkg),提交时 scope 不要带@myorg/前缀。
七、相关资源
- 配置包入口与实现:
@commitlint/config-lerna-scopes/index.js - 测试与 fixtures:
@commitlint/config-lerna-scopes/index.test.js、@commitlint/config-lerna-scopes/fixtures - 演进记录:
@commitlint/config-lerna-scopes/CHANGELOG.md - 推荐迁移目标:
@commitlint/config-workspace-scopes/index.js及对应 fixtures - 包元数据(依赖、engines、peerDependencies):
@commitlint/config-lerna-scopes/package.json
- 开发工具
- Lint
- 代码质量
【免费下载链接】commitlint
📓 Lint commit messages
相关推荐
commitlint 配置 @commitlint/config-lerna-scopes:为 Lerna 单体仓库强制校验包作用域
commitlint 配置 @commitlint/config lerna scopes:为 Lerna 单体仓库强制校验包作用域 本篇技术指南围绕 comm
开发工具Lint代码质量使用 @commitlint/config-lerna-scopes 校验 Lerna 项目提交的包作用域
使用 @commitlint/config lerna scopes 校验 Lerna 项目提交的包作用域 本指南以 @commitlint/config le
开发工具Lint代码质量@commitlint/config-pnpm-scopes:为 pnpm workspace 仓库自动生成 scope 枚举的 commitlint 共享配置
@commitlint/config pnpm scopes:为 pnpm workspace 仓库自动生成 scope 枚举的 commitlint 共享配置
开发工具Lint代码质量
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考