Skip to content

Bunup Workspaces ​

Effortlessly manage multiple packages in a monorepo with Bunup’s built-in workspace support.

This eliminates the need for separate build configurations and multiple commands for each package. With a single configuration file and a single command, you can build all your packages at once.

Creating a Workspace Configuration ​

Define your workspace using the defineWorkspace function:

bunup.config.ts
ts
import { defineWorkspace } from "bunup";

export default defineWorkspace([
  // Package configurations go here
]);

Package Configuration ​

Each package requires three properties:

PropertyTypeDescription
namestringUnique identifier for the package
rootstringPath to the package directory, relative to the monorepo root
configBunupConfig | BunupConfig[]Optional build configuration(s) for this package

👉 If you omit config, Bunup will use defaults:

Basic Usage ​

A minimal workspace with two packages:

bunup.config.ts
ts
import { defineWorkspace } from "bunup";

export default defineWorkspace([
  {
    name: "core",
    root: "packages/core",
    config: {
      // Bunup finds 'src/index.ts' by default
      // Or specify exactly which files to build
      // entry: ["src/index.ts", "src/plugins.ts"],
      format: ["esm", "cjs"],
    },
  },
  {
    name: "utils",
    root: "packages/utils",
    // Uses default entry: src/index.ts
    // Uses default format: esm
  },
]);

Here, core has custom formats, while utils works out of the box with defaults.

Shared Options ​

You can define shared options for all packages, reducing repetition:

bunup.config.ts
ts
export default defineWorkspace(
  [
    {
      name: "core",
      root: "packages/core",
      config: {
        format: ["esm"], // overrides shared format
      },
    },
    {
      name: "utils",
      root: "packages/utils",
      // config is optional, shared options apply
    },
  ],
  {
    // Shared options
    format: ["esm", "cjs"],
    exports: true,
    unused: true,
  }
);

Multiple Build Configurations ​

Each package can have multiple builds by passing an array.

Named Configurations

When using an array of build configurations, the name property is required for each configuration to identify the builds in logs and reports.

bunup.config.ts
ts
export default defineWorkspace([
  {
    name: "web",
    root: "packages/web",
    config: [
      {
        entry: "src/index.ts",
        name: "node",
        format: "esm",
        target: "node",
      },
      {
        entry: "src/browser.ts",
        name: "browser",
        format: ["esm", "iife"],
        target: "browser",
        outDir: "dist/browser",
      },
    ],
  },
]);

Another example: if you have different entry points that need different build configurations, you can specify them separately. For instance, your main module might need both ESM and CJS formats, while a CLI entry point might only need ESM:

bunup.config.ts
ts
export default defineWorkspace([
  {
    name: "main",
    root: "packages/main",
    config: [
      {
        entry: "src/index.ts",
        name: "main",
        format: ["esm", "cjs"],
      },
      {
        entry: "src/cli.ts",
        name: "cli",
        format: ["esm"],
      },
    ],
  },
]);

Path Resolution ​

All paths in package configs are relative to the package root:

myproject/
├── packages/
│   ├── core/        <- package root
│   │   ├── src/     <- entries resolved here
│   │   └── dist/    <- outputs here
│   └── utils/
├── bunup.config.ts
└── package.json

Example:

ts
{
  name: "core",
  root: "packages/core",
  config: {
    entry: "src/index.ts",  // resolves to packages/core/src/index.ts
    outDir: "dist",         // outputs to packages/core/dist/
  },
}

Plugin Paths

When using plugins (like copy), paths are also resolved relative to the package root. For example, copy("assets/**/*.svg") in the core package will copy from packages/core/assets.

Building Packages ​

Build all packages ​

sh
bunx bunup

Watch mode ​

sh
bunx bunup --watch

Bunup will watch all packages and rebuild only those that change.

Build specific packages ​

Use the --filter option with package names:

sh
bunx bunup --filter core,utils
# or in watch mode
bunx bunup --filter core,utils --watch

Incremental Builds

Workspaces are incremental: only changed packages are rebuilt.

Released under the MIT License.