Introducing the quick, lean, built by people all over the world machine-PNPM! Built on the Node.js platform, the real power of pnpm comes from its ability to squash disk space and harness the config power of npm as a pathway for commands. While I haven't had the chance to migrate files using pnpm, I am increasingly curious about using classic Unix symlink and hardlink structure to modify node modules for special projects. Pnpm has utilized these link structures to prevent bugs that occur from default behaviors in node modules. For an example illustrating pnpm strictness, read on.
A simple definition of symbolic linking in this context would be a file that is a shortcut to another file. What pnpm does via hardlink is pull data from the global store, create one version of a node module and store it only once on a disk. Symlinks function as soft connections between express, the npm registry, and the module files. This gives pnpm the ability to move dependencies to the same directory level on which the real location of the dependent package exists. If you're curious about this file structure, you can read more on module structure in pnpm.
Peer dependencies are installed laterally, higher in the dependency order. If no peers are present, the package is hard linked to node_modules using the symlink to nest dependencies, which helps prevent recirculation. Peer dependencies will be installed for each peer, and Node.js will use a module resolver algorithmn to find the correct peers.
pnpm also utilizes filtering in multiple packages of dependencies through a series of recursive style commands.
pnpm recursive install
runs installation for every package in every subfolder
pnpm recursive run build --filter foo-*
builds all packages with names that start with foo-
pnpm recursive update -- login-page...
updates dependencies in login-page and any dependencies of login-page that are also in the repository
pnpm allows you to step directly into the installation process via special functions called hooks. Hooks can be declared in a file called pnpmfile.js. pnpmfile.js should live in the root of the project.
This hook will override the manifest of foo@1 after downloading it from the registry
foo@1 will always be installed with the second version of bar
Aliases allow you to install and publish packages with special names, letting you use different versions of a package in your project. When combined with hooks, you can write a function to replace one version of a package with another in all your node_modules.
We can create a new package called
veros-magical-lodash and install it:
pnpm install lodash@npm:veros-magical-lodash Here is a pnpmfile.js that does this:
Due to the non-standard node modules structure that pnpm uses, it has some limitations:
package-lock.jsonis ignored. Because pnpm creates a different file structure, it cannot align itself with npm's lockfile format.
- Node.js doesn't work with
--preserve-symlinksflag when executed in a project that uses pnpm. If you begin working in pnpm and discover a true bug, report it to the page on Github.
To some who have had issues with dependencies and wish to revert back to npm, an npm global config workaround can help flatten files and resolve some runtime issues.
Also in the works is a new project from npm, Tink, that works to reshape the relationship between the Node.js and the npm registry, allowing you to make customized dependencies working from your package-lock.json file.
In summation, it seems that the ideal pnpm user is a fairly seasoned developer and speed freak comfortable with the intricacies of customizing packages and utilizing hooks to get specific results. If you're interested in integrating pnpm to your projects and want to learn more, visit the pnpm documentation.
I really enjoyed writing this piece and studying the core concepts of pnpm. As always, questions, comments and feedback are always welcome. Thanks for reading!