When I first started contributing to pnpm (around
v0.15), this is how an installation was reported:
It wasn’t really useful but some users of pnpm liked it. They thought it was beautiful. But then as we started adding more features, we realized that it is very important to print the right amount of information in a nice readable format.
So let’s see how pnpm has evolved and how it reports in different scenarios as of
Reporting installation in a single project
When you first install pnpm and you run
pnpm install in a project, you'll see an output like this:
Unlike the old output, this one is very static and minimalistic but it contains a lot more useful information.
We see that:
- one of the installed packages is deprecated
- 117 new packages were added to
- Installation slowed down a bit because the huge typescript tarball was being downloaded
- 0 packages were available in the store, so all 117 packages were downloaded (pnpm saves one version of a package only ever once on a disk, so when a package is available in the store, it is just hard linked to the
firstname.lastname@example.org added as a production dependency
- a newer version of express is available in the registry
email@example.com added as dev dependencies
Now lets update express to the latest version and see what we get:
- 5 packages were removed from node_modules
- 5 packages were added to node_modules
- all 5 packages were downloaded from the registry
- the newest express was added to the project
Reporting installation in a multi-package repository
pnpm has a set of commands for working with multi-package repositories (MPR). When installing dependencies in an MPR, the amount of information that is being processed is so big that printing all of it would just make an unreadable mess. In order to provide some basic information anyway, we came out with the concept of zoomed-out reporting. A zoomed-out reporting contains just the most important pieces of information.
Every package in the MPR is printed with the number of added/removed packages (inspired by Git):
Zoomed-out reporting also prints warnings (only warnings, no info messages):
When we came out with the concept of zoomed-out reporting for the recursive commands, we realized that there are other scenarios in which they are useful. For instance, when packages are linked in, it should be a mixture of zoomed-out and zoomed-in reporting. Packages that are linked in should be reported briefly and the package in the current working directory should be in focus:
Although the output seems minimalistic and simple, it is produced by a very complex system. pnpm consists of many components and many operations may happen in random order (this is one of the reasons pnpm is so fast). That is why reporting is performed by a specialized part of pnpm called “reporter” (code).
The reporter is a package that listens for logs, filters them, combines and forms an output from them. pnpm uses bole to pass the logs from the loggers to the reporter. This modularization is great because we can mock the logs and cover reporting with tests!
For printing the output to the console, we use ansi-diff.
ansi-diff is great because it accepts "frames" of output and it updates only those parts of the console that are changed (and it is fast). Before we switched to
ansi-diff, we used another popular library for updating the console output but it was doing the update with noticeable flickering.
It is very hard to implement good CLI reporting. But good reporting allows developers to focus on the important things and possibly notice issues earlier.
Of course, pnpm’s reporting can improved a lot and we have many open issues in that area. Give pnpm a try and don’t hesitate to let us know if there are things that can be improved further.