How to Use npm Workspaces for Monorepos
This article provides a practical guide on how to configure and manage a monorepo using native npm workspaces in a Node.js ecosystem. You will learn how to initialize a workspace-enabled project, structure your codebase, manage shared dependencies, and run scripts across multiple packages efficiently from a single root directory.
What are npm Workspaces?
Introduced in npm v7, workspaces allow you to manage multiple packages within a single root package. This eliminates the need for complex external tools for basic monorepo orchestration. It automatically handles symlinking, enabling packages within your repository to reference one another local-first.
Step 1: Initialize the Root Package
To begin, create a new directory for your monorepo and initialize it
with a package.json file.
mkdir my-monorepo
cd my-monorepo
npm init -yOpen the package.json file and add the
workspaces property. This property accepts an array of
globs pointing to the directories containing your sub-packages.
{
"name": "my-monorepo",
"version": "1.0.0",
"private": true,
"workspaces": [
"packages/*"
]
}Note: Marking the root package as "private": true
prevents it from being accidentally published to the npm
registry.
Step 2: Create Sub-Packages
Next, create a packages directory and set up your
individual workspaces (for example, a shared utility library and an API
service).
mkdir -p packages/shared packages/apiInitialize a package.json in each sub-package:
packages/shared/package.json:
{
"name": "@my-monorepo/shared",
"version": "1.0.0",
"main": "index.js"
}packages/api/package.json:
{
"name": "@my-monorepo/api",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@my-monorepo/shared": "^1.0.0"
}
}Step 3: Install Dependencies
Run npm install from the root directory. npm will
resolve the dependency tree, symlink @my-monorepo/shared
into the root node_modules folder, and make it available to
@my-monorepo/api without publishing it to an external
registry.
To add an external dependency (like lodash) to a
specific workspace, use the -w (workspace) flag from the
root:
npm install lodash -w @my-monorepo/sharedTo add a development dependency to all workspaces, use the
-ws flag:
npm install rimraf --save-dev -wsStep 4: Running Scripts
You can run scripts defined in individual packages directly from the
root using the -w flag. For example, if
@my-monorepo/api has a start script, run:
npm run start -w @my-monorepo/apiTo run a specific script (like a test or build script) across all
workspaces simultaneously, use the -ws flag:
npm run test -ws