Bun

目录

Bun 中的目录提供了一种在 Monorepo 中跨多个包共享通用依赖版本集的直接方式。您无需在每个工作区包中重复指定相同的版本,而是在根 package.json 中定义一次,并在整个项目中保持一致地引用它们。

概述

与传统依赖管理中每个工作区包都需要独立指定版本不同,目录允许您:

  1. 在根 package.json 中定义版本目录
  2. 使用简单的 `catalog:` 协议引用这些版本
  3. 通过只更改一处版本来同时更新所有包

这在大型 Monorepo 中特别有用,在这些 Monorepo 中,几十个包可能需要使用相同版本的关键依赖项。

如何使用目录

目录结构示例

考虑一个具有以下结构的 Monorepo:

my-monorepo/
├── package.json
├── bun.lock
└── packages/
    ├── app/
    │   └── package.json
    ├── ui/
    │   └── package.json
    └── utils/
        └── package.json

1. 在根 package.json 中定义目录

在您的根级 `package.json` 中,在 `workspaces` 对象中添加 `catalog` 或 `catalogs` 字段。

{
  "name": "my-monorepo",
  "workspaces": {
    "packages": ["packages/*"],
    "catalog": {
      "react": "^19.0.0",
      "react-dom": "^19.0.0"
    },
    "catalogs": {
      "testing": {
        "jest": "30.0.0",
        "testing-library": "14.0.0"
      }
    }
  }
}

如果您将 `catalog` 或 `catalogs` 放在 `package.json` 文件的顶层,它也同样有效。

2. 在工作区包中引用目录版本

在您的工作区包中,使用 `catalog:` 协议来引用版本。

packages/app/package.json

{
  "name": "app",
  "dependencies": {
    "react": "catalog:",
    "react-dom": "catalog:",
    "jest": "catalog:testing"
  }
}

packages/ui/package.json

{
  "name": "ui",
  "dependencies": {
    "react": "catalog:",
    "react-dom": "catalog:"
  },
  "devDependencies": {
    "jest": "catalog:testing",
    "testing-library": "catalog:testing"
  }
}

3. 运行 Bun Install

运行 `bun install` 以根据目录版本安装所有依赖项。

catalog 与 catalogs 的区别

Bun 支持两种定义目录的方式:

  1. `catalog` (单数): 用于常用依赖项的单个默认目录。

    "catalog": {
      "react": "^19.0.0",
      "react-dom": "^19.0.0"
    }
    

    只需使用 `catalog:` 引用。

    "dependencies": {
      "react": "catalog:"
    }
    
  2. `catalogs` (复数): 用于对依赖项进行分组的多个命名目录。

    "catalogs": {
      "testing": {
        "jest": "30.0.0"
      },
      "ui": {
        "tailwind": "4.0.0"
      }
    }
    

    使用 `catalog:` 引用。

    "dependencies": {
      "jest": "catalog:testing",
      "tailwind": "catalog:ui"
    }
    

使用目录的好处

  • 一致性:确保所有包使用相同版本的关键依赖项。
  • 维护:在一个地方更新依赖项版本,而不是在多个 package.json 文件中。
  • 清晰度:明确哪些依赖项在您的 Monorepo 中是标准化的。
  • 简单性:无需复杂的版本解析策略或外部工具。

实际示例

这是一个更全面的 React 应用程序示例:

根 package.json

{
  "name": "react-monorepo",
  "workspaces": {
    "packages": ["packages/*"],
    "catalog": {
      "react": "^19.0.0",
      "react-dom": "^19.0.0",
      "react-router-dom": "^6.15.0"
    },
    "catalogs": {
      "build": {
        "webpack": "5.88.2",
        "babel": "7.22.10"
      },
      "testing": {
        "jest": "29.6.2",
        "react-testing-library": "14.0.0"
      }
    }
  },
  "devDependencies": {
    "typescript": "5.1.6"
  }
}

packages/app/package.json

{
  "name": "app",
  "dependencies": {
    "react": "catalog:",
    "react-dom": "catalog:",
    "react-router-dom": "catalog:",
    "@monorepo/ui": "workspace:*",
    "@monorepo/utils": "workspace:*"
  },
  "devDependencies": {
    "webpack": "catalog:build",
    "babel": "catalog:build",
    "jest": "catalog:testing",
    "react-testing-library": "catalog:testing"
  }
}

packages/ui/package.json

{
  "name": "@monorepo/ui",
  "dependencies": {
    "react": "catalog:",
    "react-dom": "catalog:"
  },
  "devDependencies": {
    "jest": "catalog:testing",
    "react-testing-library": "catalog:testing"
  }
}

packages/utils/package.json

{
  "name": "@monorepo/utils",
  "dependencies": {
    "react": "catalog:"
  },
  "devDependencies": {
    "jest": "catalog:testing"
  }
}

更新版本

要更新所有包的版本,只需更改根 `package.json` 中的版本:

"catalog": {
  "react": "^19.1.0",  // Updated from ^19.0.0
  "react-dom": "^19.1.0"  // Updated from ^19.0.0
}

然后运行 `bun install` 来更新所有包。

锁文件集成

Bun 的锁文件跟踪目录版本,从而轻松确保在不同环境中安装的一致性。锁文件包括:

  • 您的 package.json 中的目录定义
  • 每个目录依赖项的解析
// bun.lock (excerpt)
{
  "lockfileVersion": 1,
  "workspaces": {
    "": {
      "name": "react-monorepo",
    },
    "packages/app": {
      "name": "app",
      "dependencies": {
        "react": "catalog:",
        "react-dom": "catalog:",
        ...
      },
    },
    ...
  },
  "catalog": {
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    ...
  },
  "catalogs": {
    "build": {
      "webpack": "5.88.2",
      ...
    },
    ...
  },
  "packages": {
    ...
  }
}

限制和边缘情况

  • 目录引用必须与 `catalog` 或其中一个命名 `catalogs` 中定义的依赖项匹配
  • 目录名称中的空字符串和空格将被忽略(视为默认目录)
  • 目录中无效的依赖项版本将在 `bun install` 期间解析失败
  • 目录仅在工作区内可用;它们不能在 Monorepo 之外使用

Bun 的目录系统提供了一种强大而简单的方法,可以在不增加工作流程额外复杂性的情况下保持 Monorepo 的一致性。

发布

当您运行 `bun publish` 或 `bun pm pack` 时,Bun 会自动替换: 您 `package.json` 中的 `catalog:` 引用替换为解析后的版本号。 发布的包包含常规的语义版本字符串,并且不再依赖于 您的目录定义。