115 lines
4.2 KiB
Plaintext
115 lines
4.2 KiB
Plaintext
---
|
||||
|
|
title: "Workspaces"
|
|||
|
|
description: "Develop complex monorepos with multiple independent packages"
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
Bun supports [`workspaces`](https://docs.npmjs.com/cli/v9/using-npm/workspaces?v=true#description) in `package.json`. With workspaces, you develop several independent packages in a single repository, a _monorepo_.
|
|||
|
|
|
|||
|
|
A monorepo commonly has this structure:
|
|||
|
|
|
|||
|
|
```txt File Tree icon="folder-tree"
|
|||
|
|
<root>
|
|||
|
|
├── README.md
|
|||
|
|
├── bun.lock
|
|||
|
|
├── 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
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The `"workspaces"` key in the root `package.json` lists the subdirectories to treat as workspaces. By convention, they live in a directory called `packages`.
|
|||
|
|
|
|||
|
|
```json package.json icon="file-json"
|
|||
|
|
{
|
|||
|
|
"name": "my-project",
|
|||
|
|
"version": "1.0.0",
|
|||
|
|
"workspaces": ["packages/*"],
|
|||
|
|
"devDependencies": {
|
|||
|
|
"example-package-in-monorepo": "workspace:*"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<Note>
|
|||
|
|
**Glob support** — Bun supports full glob syntax in `"workspaces"`, including negative patterns such as
|
|||
|
|
`!**/excluded/**`. See [supported glob patterns](/runtime/glob#supported-glob-patterns).
|
|||
|
|
</Note>
|
|||
|
|
|
|||
|
|
```json package.json icon="file-json"
|
|||
|
|
{
|
|||
|
|
"name": "my-project",
|
|||
|
|
"version": "1.0.0",
|
|||
|
|
"workspaces": ["packages/**", "!packages/**/test/**", "!packages/**/template/**"]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Each workspace has its own `package.json`. To reference another package in the monorepo, use a semver range or the workspace protocol (for example `workspace:*`) as the version in your `package.json`.
|
|||
|
|
|
|||
|
|
```json packages/pkg-a/package.json icon="file-json"
|
|||
|
|
{
|
|||
|
|
"name": "pkg-a",
|
|||
|
|
"version": "1.0.0",
|
|||
|
|
"dependencies": {
|
|||
|
|
"pkg-b": "workspace:*"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`bun install` installs dependencies for all workspaces in the monorepo, de-duplicating packages if possible. To install dependencies for specific workspaces only, use the `--filter` flag.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Install dependencies for all workspaces starting with `pkg-` except for `pkg-c`
|
|||
|
|
bun install --filter "pkg-*" --filter "!pkg-c"
|
|||
|
|
|
|||
|
|
# Paths can also be used. This is equivalent to the command above.
|
|||
|
|
bun install --filter "./packages/pkg-*" --filter "!pkg-c" # or --filter "!./packages/pkg-c"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
When publishing, Bun replaces `workspace:` versions with the package's `package.json` version:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
"workspace:*" -> "1.0.1"
|
|||
|
|
"workspace:^" -> "^1.0.1"
|
|||
|
|
"workspace:~" -> "~1.0.1"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
A specific version takes precedence over the package's `package.json` version:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
"workspace:1.0.2" -> "1.0.2" // Even if current version is 1.0.1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Workspaces have a few major benefits.
|
|||
|
|
|
|||
|
|
- **Split code into logical parts.** If one package relies on another, add it as a dependency in `package.json`. If package `b` depends on `a`, `bun install` installs your local `packages/a` directory into `node_modules` instead of downloading it from the npm registry.
|
|||
|
|
- **Bun can de-duplicate dependencies.** If `a` and `b` share a common dependency, Bun _hoists_ it to the root `node_modules` directory. This saves disk space and minimizes the "dependency hell" of multiple versions of a package installed at once.
|
|||
|
|
- **Run scripts in multiple packages.** Use the [`--filter` flag](/pm/filter) to run `package.json` scripts in several packages at once, or `--workspaces` to run scripts across all workspaces.
|
|||
|
|
|
|||
|
|
## Share versions with Catalogs
|
|||
|
|
|
|||
|
|
When many packages need the same dependency versions, define those versions once
|
|||
|
|
in a catalog in the root `package.json` and reference them from your workspaces
|
|||
|
|
with the `catalog:` protocol. Updating the catalog updates every package that
|
|||
|
|
references it. See [Catalogs](/pm/catalogs).
|
|||
|
|
|
|||
|
|
<Note>
|
|||
|
|
⚡️ **Speed** — Installs are fast, even for big monorepos. Bun installs the [Remix](https://github.com/remix-run/remix) monorepo in about `500ms` on Linux.
|
|||
|
|
|
|||
|
|
- 28x faster than `npm install`
|
|||
|
|
- 12x faster than `yarn install` (v1)
|
|||
|
|
- 8x faster than `pnpm install`
|
|||
|
|
|
|||
|
|
<Image src="https://user-images.githubusercontent.com/709451/212829600-77df9544-7c9f-4d8d-a984-b2cd0fd2aa52.png" />
|
|||
|
|
</Note>
|