Symlinked `node_modules` structure

    This article only describes how pnpm’s are structured when there are no packages with peer dependencies. For the more complex scenario of dependencies with peers, see how peers are resolved.

    pnpm’s node_modules layout uses symbolic links to create a nested structure of dependencies.

    Every file of every package inside node_modules is a hard link to the content-addressable store. Let’s say you install foo@1.0.0 that depends on bar@1.0.0. pnpm will hard link both packages to node_modules like this:

    As you might have noticed, both packages are hard linked into a subfolder inside a node_modules folder (foo@1.0.0/node_modules/foo). This is needed to:

    The next stage of installation is symlinking dependencies. bar is going to be symlinked to the foo@1.0.0/node_modules folder:

    Next, direct dependencies are handled. foo is going to be symlinked into the root node_modules folder because foo is a dependency of the project:

    Let’s add qar@2.0.0 as a dependency of bar and . This is how the new structure will look:

    As you may see, even though the graph is deeper now (foo > bar > qar), the directory depth in the file system is still the same.

    This layout might look weird at first glance, but it is completely compatible with Node’s module resolution algorithm! When resolving modules, Node ignores symlinks, so when bar is required from foo@1.0.0/node_modules/foo/index.js, Node does not use bar at foo@1.0.0/node_modules/bar, but instead, bar is resolved to its real location (bar@1.0.0/node_modules/bar). As a consequence, bar can also resolve its dependencies which are in bar@1.0.0/node_modules.