要在 Mac 上的 npm 各软件包之间统一依赖项,首先要对比各个工作区 package.json 中的版本范围,确定适合每个软件包的通用版本范围,然后更新每个受影响的工作区并重新生成根锁定文件。npm 工作区可以从仓库根目录定位各个软件包,但并未提供内置命令来扫描每个清单并自动使依赖版本完全一致。

1. 检查仓库是否使用 npm 工作区

在终端中,切换到仓库根目录并检查其配置:

cd "/path/to/your/repository"
npm --version
npm pkg get workspaces

根目录的 package.json 应定义工作区路径,并且每个软件包都应有自己的 package.json。npm 的工作区功能会在安装过程中链接这些本地软件包,并允许命令按名称或路径定位一个或多个工作区。如果 npm pkg get workspaces 未返回任何内容,请在使用 npm 工作区命令之前确认仓库的包管理器和目录结构。npm 工作区

2. 比较依赖项声明

在已纳入版本控制的清单中搜索要统一的依赖项。例如,在 macOS 终端中,你可以直接使用 grep,无需安装额外工具:

grep -n '"typescript"' package.json packages/*/package.json

将 typescript 替换为相应的依赖项名称。这只是一项快速的文本检查,因此请查看每个清单中的匹配部分,确认该软件包是属于 dependencies、devDependencies、peerDependencies 还是 optionalDependencies。这些字段代表不同的用途;切勿仅仅为了让版本字符串保持一致而随意跨字段移动依赖项。要获取更完整的清单目录,可以在编辑器中检查每个工作区清单,或使用 npm 支持工作区的列表命令:

npm ls typescript --workspaces --depth=0

清单中的范围与实际安装的依赖树解决的是不同的问题:前者表明每个软件包允许的版本,而 npm ls 报告的是已安装的依赖项状态。npm 的锁定文件记录了解析后的版本,但它并不能取代各个 package.json 中声明的允许范围。npm ls package-lock.json 与 npm install

3. 选择兼容的版本策略

挑选一个既能满足使用者要求、又符合仓库支持策略的版本。共享的版本范围意味着各个软件包声明了相同的允许集合;这并不能保证所有嵌套或传递副本都会解析为单个已安装的副本。在跨主版本迁移软件包之前,请检查 peer 依赖需求和更新日志中的破坏性变更。如果使用者需要更宽泛的兼容范围,统一为完全相同的字符串可能并不合适;此时应就等效的范围策略达成一致。

例如,要将名为 web 和 api 的两个工作区中的某个开发工具设置为完全相同的版本,请在根目录下运行以下命令:

npm install --save-dev --save-exact typescript@5.8.3 --workspace=web --workspace=api

请使用你项目中选定的版本;此处的 5.8.3 仅为示例。npm 的 install 命令支持工作区选择器,并将软件包保存到每个选定软件包的清单中。--save-exact 会写入确切版本,而不是 npm 通常使用的范围操作符。对于运行时依赖项,请使用相应的保存类别(例如 --save-prod)代替 --save-dev。npm install

对其他工作区选择器重复此操作,或者为每个工作区分别运行该命令。不要假定根目录级别的安装会自动更新每个软件包清单:必须明确指定那些声明需要更改的软件包。如果根软件包也需要声明相同的依赖项,可以使用 --include-workspace-root 显式将其包含在内。

4. 重新安装、检查差异并验证

更新声明后,在仓库根目录运行安装,以便 npm 协调工作区依赖树和锁定文件:

npm install
npm ls typescript --workspaces --depth=0
git diff -- package.json package-lock.json packages/*/package.json

检查每个目标清单是否都包含约定好的声明,并确认锁定文件的更改符合预期。运行仓库相关的构建或测试脚本;单凭 npm ls 无法确认代码能否与所选版本正常协同工作。当项目对根目录的 package-lock.json 进行版本控制时,请将其提交,以便团队成员在安装时能够复现已解析的依赖树。npm package-lock 文档

如果 npm 报告无效依赖项或 peer 冲突,请检查错误中指明的软件包,而不是强制安装。可能是某个工作区需要不同的兼容范围,或者另一个依赖项施加了需要审慎制定升级计划的 peer 需求。

何时使用 npm dedupe

npm dedupe 可以通过将兼容的依赖项提升到更高层级供软件包共享,从而简化已安装的依赖树。它不会重写 package.json 中的直接依赖范围,因此其自身无法统一依赖声明。请仅在确认版本范围兼容之后使用它,然后检查生成的锁定文件差异。npm dedupe

最稳妥的做法是在每个相关的工作区清单中体现出深思熟虑的策略、重新生成锁定文件,并验证受影响的软件包。这样不仅能为维护者留下清晰的统一记录,还能让不兼容的限制条件显现出来,以便单独做出决策。

来源