pnpm
Overview
Section titled “Overview”pnpm is a drop-in replacement for npm that is faster and has more features.
- To migrate code from
npm, just deletenode_modulesandpackage-lock.json, then dopnpm install(reference). pnpm patchcan patch dependencies, e.g. to address a bug in a library without having to wait for them to publish a fix.pnpm addandpnpm installare very similar. In general, when adding a dependency, usepnpm addsince it will only handle installs related to the new dependency.
Patching
Section titled “Patching”If one of your dependencies has a small issue that you’d like to fix immediately without going through the PR process, then you can just patch that dependency.
Rather than use the official pnpm patch directly (reference), you can use pnpm-patch-i, which is a “better and interactive pnpm patch”. Here are the instructions that I used:
npx pnpm-patch-i kysely-migration-cli- It’ll ask to install
pnpm-patch-i
- It’ll ask to install
- If it fails to open the editor, then you can just manually open the path that it spits out, e.g.
node_modules/.patch-edits/patch_edit_your-dep-name_5ccfb173d2- In the editor that opens. you’ll have the entire module that you’re patching available to you, so just make any changes to it.
- After making changes, make sure to press enter and not escape even though the error is what printed last. It should commit your changes.
- In the editor that opens. you’ll have the entire module that you’re patching available to you, so just make any changes to it.
Workspaces (reference)
Section titled “Workspaces (reference)”Getting started:
- See this repo as an example of how to use workspaces.
- You need to make
packages/YOUR_FIRST_PACKAGEand split yourpackage.jsonfile.- Your root-level
package.jsonshould contain only tooling related to the whole project, e.g.eslint,prettier,husky, etc. - Your package-specific
package.jsonshould contain any specific configuration. For example, that’s where your test library should exist, any overrides for linting ortsconfig.json, etc.
- Your root-level
- If linting fails after you’ve set up your packages, try deleting the linting cache in all directories (e.g.
.eslintcache) - Running tests from the root is not advised unless you’re running them from CI; just run them in the individual packages.
- You can run a
pnpmscript on a specific set of workspaces with filtering (reference), e.g.pnpm --filter "abbott-bots" run build - Doing
pnpm iin the root level will installnode_modulesfor all packages. - Once you have multiple packages, you need to set up references between them. See this resource.
- Note: even packages that don’t depend on other packages yet should get
compositeset totrue. See the documentation forcomposite. This letstsc --buildskip it if you didn’t change it
- Note: even packages that don’t depend on other packages yet should get
Astro and monorepos
Section titled “Astro and monorepos”Suppose you have a web package that you’re making and it depends on a database package in the same monorepo. By default, pnpm build on the Astro project will not run tsc, so it won’t rebuild the database package. This can be confusing since you may expect changes in the database package to automatically get picked up. It’s easy to fix:
- Install
typescript:pnpm add -D typescript - Add
tsc --build --force &&to the beginning of yourbuildcommand inweb’spackage.json - Probably make sure that your
webpackage’stsconfigdoesn’t have anincludeproperty.
Adding a new package to a monorepo
Section titled “Adding a new package to a monorepo”For reference projects that uses a monorepo, take a look at:
- Abbott (which I made (◕‿◕✿)).
- https://github.com/bakeruk/modern-typescript-monorepo-example
Instructions on how to add a new package:
- Make sure you have a
package.jsonin the new package. You can initialize one withpnpm init. You will probably needbuildandwatchscripts and anexportssection, so consider copying contents from an existingpackage.jsonto get those fields. - Make sure you have a
tsconfig.jsonin the new package. You can typically just copy one from another part of your project.- Modify
pathsandreferencesas mentioned in this blog post so that you’re referring to any dependencies.
- Modify
- If you use
eslint, copy over.eslintrc.cjsso that linting will work properly. - In the new package, you should probably have an
index.tswhich can be a “barrel”. It should be in yoursrcdirectory and yourtsconfig.jsonshould have arootDirwhich containsindex.ts. - Suppose
package-adepends onpackage-b.- You would need to add this to
package-a’spackage.json’s dependencies:"package-b": "workspace:*"
- You need to modify
package-a’stsconfig.jsonto addcompilerOptions.pathsandreferences.
- You would need to add this to
- Run
pnpm ito set up the symlinks between packages. - If you run into issues where you can’t import a package defined in the workspace, then try restarting VSCode (or just the extension host).
Troubleshooting
Section titled “Troubleshooting”ERR_PNPM_REGISTRIES_MISMATCH
Section titled “ERR_PNPM_REGISTRIES_MISMATCH”If you get an error like this:
ERR_PNPM_REGISTRIES_MISMATCH This modules directory was created using the following registries configuration: {"@fortawesome":"https://npm.fontawesome.com/","default":"https://registry.npmjs.org/"}. The current configuration is {"default":"https://registry.npmjs.org/"}. To recreate the modules directory using the new settings, run "pnpm install".…then just run pnpm i and have it recreate the entire node_modules directory. If the command causing the original error was pnpm add, then make sure to run it again!