运行时包管理器打包器测试运行器代码检查格式化指南参考博客反馈

覆盖与解析

使用 npm 的 overrides 和 Yarn 的 resolutions 控制元依赖版本

Bun 支持 package.json 中 npm 的 "overrides" 和 Yarn 的 "resolutions"。两者都为_元依赖_(即你的依赖项的依赖)指定版本范围。

package.json
{
  "name": "my-app",
  "dependencies": {
    "foo": "^2.0.0"
  },
  "overrides": { // [!code ++]
    "bar": "~4.4.0" // [!code ++]
  } // [!code ++]
}

默认情况下,Bun 会根据每个包的 package.json 中指定的版本范围,安装所有依赖项和元依赖项的最新版本。假设你的项目有一个依赖项 foo,而 foo 又依赖于 bar。这使得 bar 成为项目的一个_元依赖项_。

package.json
{
  "name": "my-app",
  "dependencies": {
    "foo": "^2.0.0"
  }
}

当你运行 bun install 时,Bun 会安装每个包的最新版本。

tree
node_modules
├── foo@2.3.4
└── bar@4.5.6

如果 bar@4.5.6 中引入了安全漏洞,你可能会想要将 bar 固定到一个不包含该漏洞的旧版本。这就是 "overrides" 和 "resolutions" 的用途。


"overrides"

将 bar 添加到 package.json 的 "overrides" 字段中。Bun 在确定要安装哪个版本的 bar 时,会遵循指定的版本范围,无论它是依赖项还是间接依赖项。

package.json
{
  "name": "my-app",
  "dependencies": {
    "foo": "^2.0.0"
  },
  "overrides": { // [!code ++]
    "bar": "~4.4.0" // [!code ++]
  } // [!code ++]
}

Bun 只会从根目录的 package.json 读取 overrides,而不会从工作区包中读取。Overrides 也会应用于 peerDependencies。

"resolutions"

"resolutions" 是 Yarn 对 "overrides" 的替代方案,语法类似。Bun 支持它,以帮助项目从 Yarn 迁移。

package.json
{
  "name": "my-app",
  "dependencies": {
    "foo": "^2.0.0"
  },
  "resolutions": { // [!code ++]
    "bar": "~4.4.0" // [!code ++]
  } // [!code ++]
}

值

值可以是任何依赖项说明符,而不仅仅是版本范围。npm: 会将一个包替换为一个分支版本,而 catalog:(或 catalog:<name>)会使被覆盖的版本与一个工作区 catalog保持同步:

package.json
{
  "name": "my-app",
  "overrides": {
    "quux": "npm:@myorg/quux@^1.0.0",
    "foo": "catalog:"
  }
}

"$name" 值会复用你在自己的依赖项中为 name 声明的范围,因此"bar": "$foo"会将 bar 固定到你为 foo 声明的范围

嵌套覆盖

你可以将规则限定到一个父包,因此它仅适用于该包的直接依赖项。Bun 接受 npm 对象形式、pnpm 的 > 形式,以及带版本范围的父包:

package.json
{
  "name": "my-app",
  "overrides": {
    "micromatch": {
      ".": "^4.0.5",
      "picomatch": "^2.3.2"
    },
    "micromatch>picomatch": "^2.3.2",
    "micromatch@^4>picomatch": "^2.3.2"
  }
}

对象中的"."会覆盖 micromatch 本身,其效果类似于顶层的"micromatch"规则

"resolutions" 接受 Yarn 的路径形式。Bun 为了兼容性接受 **,但无论哪种形式,该规则都只会影响父包的直接依赖项:

package.json
{
  "name": "my-app",
  "resolutions": {
    "micromatch/picomatch": "^2.3.2",
    "**/micromatch/**/picomatch": "^2.3.2"
  }
}

当多个规则匹配时,最具体的规则优先:带版本的父包 > 父包 > 顶层

版本范围覆盖

键可以携带版本选择器,因此规则只会应用于声明范围与其重叠的依赖包。这是 pnpm audit --fix 写入的形式:

package.json
{
  "name": "my-app",
  "overrides": {
    "semver@<7.5.2": "7.5.2",
    "webpack>terser@4": "4.8.1",
    "terser@4": {
      ".": "4.8.1"
    }
  }
}

Bun 会将选择器与每个依赖方_声明_的范围进行比较,而不是与解析后的版本进行比较。"semver@<7.5.2" 会应用于声明 ^7.3.0 的依赖方(它仍可能选择 7.3.x),但不会应用于声明 ^7.5.2 的依赖方。使用 dist-tag、catalog:、workspace:、git 或 URL 说明符的依赖方永远不会匹配选择器。

限制

  • Bun 仅支持一层父包。它会忽略 a>b>c、a/b/c 和更深层的对象嵌套,并发出警告。
  • Bun 不支持 pnpm 的 "pkg@"(空选择器)和 "-"(移除依赖项)形式,并会跳过它们,同时发出警告。
  • Bun 会将包含嵌套规则或版本范围规则的锁文件写为 lockfileVersion 3,较旧版本的 Bun 无法读取。