Mastering workspaces in package.json: A Simple Path to Scalable Monorepos
As your JavaScript or TypeScript projects grow, maintaining them as a collection of separate Git repositories can become chaotic. That’s where monorepos and workspaces step in to make life easier.
Whether you're managing a design system, an API, a CLI, or even multiple microservices, the workspaces
feature in package.json
allows you to organize all related packages within a single repository. This article breaks down what workspaces
are, why they matter, how they work, and what you need to be aware of when using them.
What Are Workspaces?
A workspace is essentially a standalone npm package located in a subdirectory of your project. With the workspaces
field in your root package.json
, you tell npm
or Yarn
to treat these subdirectories as first-class packages, which can be linked locally, share dependencies, and be managed together.
{
"private": true,
"workspaces": ["packages/*"]
}
This tells the package manager to treat every folder inside packages/
as a workspace.
Important: Your rootpackage.json
must have"private": true
to enable workspaces.
Why Use Workspaces?
Here’s why many developers adopt workspaces in monorepos:
- Local package linking: No need to publish internal packages just to use them — they're linked instantly.
- Single dependency tree: Shared dependencies like React or TypeScript are deduplicated.
- Centralized commands: You can install, test, lint, or build across all packages from one place.
- Atomic installs: A single
npm install
(oryarn install
) sets everything up. - Cross-package development: Changes in one package can instantly affect another that depends on it — no
npm publish
, nonpm install ../relative/path
.
A Simple Example Structure
my-monorepo/
├── package.json ← Root config
├── packages/
│ ├── core-lib/
│ │ └── package.json
│ ├── api-server/
│ │ └── package.json
│ └── frontend-app/
│ └── package.json
Each of these subdirectories is its own npm package — fully versioned and self-contained — but aware of each other thanks to workspaces.
How They Interact
Suppose you have @my/core-lib
being used by both @my/api-server
and @my/frontend-app
.
core-lib/package.json
:
{
"name": "@my/core-lib",
"version": "1.0.0",
"main": "index.js"
}
api-server/package.json
:
{
"name": "@my/api-server",
"dependencies": {
"@my/core-lib": "^1.0.0"
}
}
Now, when you run npm install
from the root, npm links @my/core-lib
locally — it won’t fetch it from the npm registry. This makes development blazingly fast, and version bumps can be managed manually or with release tools like Changesets.
Commands at Scale
With workspaces, you can:
npm install # Installs everything in all workspaces
npm run build -w @my/core-lib # Run build only in core-lib
npm run test --workspaces # Run test in all workspaces
You can also use powerful tools like Lerna or TurboRepo on top for task orchestration.
When Should You Use Workspaces?
Use workspaces if you:
- Maintain multiple packages that need to be developed and versioned together.
- Have a backend, frontend, and shared logic that are logically separated but live in one repo.
- Want better control of internal packages without publishing to npm.
- Prefer a modular project structure that supports reuse and clean boundaries.
Things to Watch Out For
- Dependency conflicts: If multiple workspaces use different versions of a package, resolving the tree can get messy.
- Overhead: For small projects, workspaces may be overkill.
- Tooling compatibility: Not all older tools or CI systems support workspaces smoothly.
- Deployment: You'll need to carefully decide how to build and deploy each workspace independently or as a group.
Bonus Tips
- You can define custom folder names like
"apps/*"
or"modules/*"
instead ofpackages/*
. npm@9+
supportsnpm workspaces foreach
to run commands across workspaces with better control.- Combine with TypeScript’s project references to build TypeScript workspaces incrementally.
Finally
Workspaces are a powerful tool to help scale JavaScript and TypeScript codebases. They promote modularity, reuse, and developer productivity. While they might not be necessary for every project, they’re essential for monorepos and large-scale applications with multiple interdependent packages.
If you're still building projects by copying shared logic between folders or pushing internal libraries to npm just for reuse, it's time to look into workspaces — they’ll simplify your workflow more than you expect.
Comments ()