Configuring a monorepo using workspaces
Bun's package manager supports npm "workspaces". Workspaces split a codebase into distinct packages that live in the same repository, can depend on each other, and (when possible) share a node_modules directory.
Clone this sample project to experiment with workspaces.
The root package.json should not contain "dependencies", "devDependencies", or other dependency fields. Each package should be self-contained and declare its own dependencies. It's conventional to declare "private": true to avoid accidentally publishing the root package to npm.
{
"name": "my-monorepo",
"private": true,
"workspaces": ["packages/*"]
}It's common to place all packages in a packages directory. The "workspaces" field in package.json supports glob patterns, so packages/* treats each subdirectory of packages as a separate package (also known as a workspace).
.
├── package.json
├── node_modules
└── packages
├── stuff-a
│ └── package.json
└── stuff-b
└── package.jsonTo add dependencies between workspaces, use the "workspace:*" syntax. The following adds stuff-a as a dependency of stuff-b.
{
"name": "stuff-b",
"dependencies": {
"stuff-a": "workspace:*"
}
}Once you add the dependency, run bun install from the project root to install dependencies for all workspaces.
bun installTo add npm dependencies to a particular workspace, cd to that directory and run bun add as you normally would. Bun detects that you are in a workspace, adds the dependency to that workspace's package.json, and updates the root lockfile. New workspaces use isolated installs by default, so Bun installs the package into the root node_modules/.bun store and symlinks it from the workspace's own node_modules. With --linker hoisted, Bun hoists the package into the root node_modules instead.
cd packages/stuff-a
bun add zodSee bun install.