Bun

Workspaces

Bun supports workspaces in package.json. Workspaces make it easy to develop complex software as a monorepo consisting of several independent packages.

It's common for a monorepo to have the following structure:

tree
<root>
├── README.md
├── bun.lockb
├── package.json
├── tsconfig.json
└── packages
    ├── pkg-a
    │   ├── index.ts
    │   ├── package.json
    │   └── tsconfig.json
    ├── pkg-b
    │   ├── index.ts
    │   ├── package.json
    │   └── tsconfig.json
    └── pkg-c
        ├── index.ts
        ├── package.json
        └── tsconfig.json

In the root package.json, the "workspaces" key is used to indicate which subdirectories should be considered packages/workspaces within the monorepo. It's conventional to place all the workspace in a directory called packages.

{
  "name": "my-project",
  "version": "1.0.0",
  "workspaces": ["packages/*"],
  "devDependencies": {
    "example-package-in-monorepo": "workspace:*"
  }
}

Glob support — Bun supports full glob syntax in "workspaces" (see here for a comprehensive list of supported syntax), except for exclusions (e.g. !**/excluded/**), which are not implemented yet.

Each workspace has it's own package.json. When referencing other packages in the monorepo, semver or workspace protocols (e.g. workspace:*) can be used as the version field in your package.json.

{
  "name": "pkg-a",
  "version": "1.0.0",
  "dependencies": {
    "pkg-b": "workspace:*"
  }
}

Workspaces have a couple major benefits.

  • Code can be split into logical parts. If one package relies on another, you can simply add it as a dependency in package.json. If package b depends on a, bun install will install your local packages/a directory into node_modules instead of downloading it from the npm registry.
  • Dependencies can be de-duplicated. If a and b share a common dependency, it will be hoisted to the root node_modules directory. This reduces redundant disk usage and minimizes "dependency hell" issues associated with having multiple versions of a package installed simultaneously.
  • Run scripts in multiple packages. You can use the --filter flag to easily run package.json scripts in multiple packages in your workspace.

⚡️ Speed — Installs are fast, even for big monorepos. Bun installs the Remix monorepo in about 500ms on Linux.

  • 28x faster than npm install
  • 12x faster than yarn install (v1)
  • 8x faster than pnpm install