(Updated: )
/ #javascript #node #meta 

Yarn Workspaces: monorepo management without Lerna for applications and coding examples

How to use Yarn Workspaces to manage applications/coding examples.

Lerna isn’t required when you don’t need the git diffing and versioning facilites.

What’s more Yarn Workspaces are a great lightweight tool to get up and running faster for simple Node.js monorepo actions.

Example monorepo at: github.com/HugoDF/yarn-workspaces-simple-monorepo

Table of Contents

Yarn Workspaces vs Lerna

Pros of using workspaces: Yarn Workspaces are part of the standard Yarn toolchain (not downloading an extra dependency). It’s very limited in scope, and de-dupes your installs (ie. makes them faster). This is perfect for managing code examples or a monorepo of applications.

Cons of workspaces: If you’re dealing with a monorepo of packages (npm modules, libraries), Lerna provides tooling around publishing/testing only changed files.

Note: Lerna and Yarn Workspaces are in fact designed to work together, just use "npmClient": "yarn" in your lerna.json. See the Yarn Workspaces Documentation for a short word about the comparison to Lerna.

Set up Yarn Workspaces

{
  "private": true,
  "workspaces": [ "examples/*", "other-example"]
}

The directory structure looks like the following:

graph LR;
    r[root];
    r-->example;
    example-->example-1;
    example-->example-2;
    r-->other-example;

Note: each of the workspaces (packages) need to have a package.json with a unique name and a valid version. The root package.json doesn’t need to, it just needs to have "private": true and "workspaces": [].

Bootstrapping the monorepo

Equivalent with Lerna would include a lerna bootstrap, which run npm install in all the packages.

With workspaces since the dependencies are locked from root, you just need to do a yarn at the top-level.

For workspaces to work, your “workspace” folders need to have a package.json that contain a name and version.

Managing your monorepo with yarn workspace and yarn workspaces commands

Run commands in a single package

To run commands in a single package in your monorepo, use the following syntax:

yarn workspace <package-name> <yarn-command>

For example:

$ yarn workspace example-1 run test

yarn workspace v1.x.x
yarn run v1.x.x
$ node test.js
test from example 1
✨  Done in 0.23s.
✨  Done in 0.86s.

or

$ yarn workspace example-2 remove lodash.omit

yarn workspace v1.x.x
yarn remove v1.x.x
[1/2] πŸ—‘  Removing module lodash.omit...
[2/2] πŸ”¨  Regenerating lockfile and installing missing dependencies...
success Uninstalled packages.
✨  Done in 2.83s.
✨  Done in 3.58s.

“package-name” should be the value of found in the package.json under the name key.

Run commands in all packages

To run commands in every package in your monorepo, use the following syntax:

yarn workspaces <yarn-command>

For example:

$ yarn workspaces run test

yarn workspaces v1.x.x
yarn run v1.x.x
$ node test.js
test from example 1
✨  Done in 0.22s.
yarn run v1.x.x
$ node test.js
{ public: 'data' } 'Should not display "secret"'
✨  Done in 0.23s.
yarn run v1.x.x
$ echo "Other Example"
Other Example
✨  Done in 0.11s.
✨  Done in 2.15s.

or

$ yarn workspaces run add lodash.omit@latest

yarn workspaces v1.x.x
yarn add v1.x.x
[1/4] πŸ”  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] πŸ”—  Linking dependencies...
[4/4] πŸ”¨  Building fresh packages...
success Saved 1 new dependency.
info Direct dependencies
info All dependencies
└─ [email protected]
✨  Done in 3.31s.
yarn add v1.x.x
[1/4] πŸ”  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] πŸ”—  Linking dependencies...
[4/4] πŸ”¨  Building fresh packages...
success Saved 1 new dependency.
info Direct dependencies
info All dependencies
└─ [email protected]
✨  Done in 2.76s.
yarn add v1.x.x
[1/4] πŸ”  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] πŸ”—  Linking dependencies...
[4/4] πŸ”¨  Building fresh packages...
success Saved 1 new dependency.
info Direct dependencies
info All dependencies
└─ [email protected]
✨  Done in 2.63s.
✨  Done in 10.82s.

Example monorepo at: github.com/HugoDF/yarn-workspaces-simple-monorepo

unsplash-logoMartin Adams

Author

Hugo Di Francesco

Co-author of "Professional JavaScript", "Front-End Development Projects with Vue.js" with Packt, "The Jest Handbook" (self-published). Hugo runs the Code with Hugo website helping over 100,000 developers every month and holds an MEng in Mathematical Computation from University College London (UCL). He has used JavaScript extensively to create scalable and performant platforms at companies such as Canon, Elsevier and (currently) Eurostar.

Get The Jest Handbook (100 pages)

Take your JavaScript testing to the next level by learning the ins and outs of Jest, the top JavaScript testing library.