Both pnpm (as of v2.17) and Yarn (as of v1.12) support fast, concurrent installations in monorepos. However, there is a big difference between how they store dependencies in monorepos. Yarn tries to hoist all dependencies from all workspace packages into the root node_modules of the monorepo, which means that packages have access to dependencies of other packages in the workspace. This is described in the Yarn docs:

Be careful when publishing packages in a workspace. If you are preparing your next release and you decided to use a new dependency but forgot to declare it in the package.json file, your tests might still pass locally if another package already downloaded that dependency into the workspace root. However, it will be broken for consumers that pull it from a registry, since the dependency list is now incomplete so they have no way to download the new dependency. Currently, there is no way to throw a warning in this scenario.

Like Yarn, pnpm hoists all packages to the root. However, pnpm stores all dependencies in a hidden folder and only links the direct dependencies of every package into their node_modules .

Let’s see how Yarn and pnpm work on a simple example:

there is a small monorepo with two packages: foo and bar

and foo has is-negative@1.0.0 as a dependency

has as a dependency bar has is-positive@1.0.0 as a dependency

Yarn in action

To make this repo work with Yarn, there should be a package.json in the root of the repo with the following content:

{

"private": true,

"workspaces": ["foo", "bar"]

}

To install all dependencies of all workspace packages, you should run yarn install .

See results here

In this case, Yarn will create a single node_modules in the root of the repo with both is-negative and is-positive . It means that both foo and bar will have access to the dependencies of each other.

pnpm in action

To make pnpm install dependencies in this repo, you’ll need to create a pnpm-workspace.yaml in the root of the repo (it can be empty) and a .npmrc file with the following content:

shared-workspace-shrinkwrap = true

link-workspace-packages = true

To install all dependencies of all workspace packages with pnpm, you should run pnpm multi install (or just pnpm m i ).

See results here

Like Yarn, pnpm creates a node_modules in the root of the repo. However, if you open that folder, you'll see that all directories and files are hidden there:

node_modules

+ .registry.npmjs.org

+ .modules.yaml

+ .shrinkwrap.yaml

This node_modules stores all the dependencies but they are hidden in .registry.npmjs.org . Node's resolution algorithm will not find them.