pnpm
Overview
Section titled Overviewpnpm
is a drop-in replacement for npm
that is faster and has more features.
- To migrate code from
npm
, just deletenode_modules
andpackage-lock.json
, then dopnpm install
(reference). pnpm patch
can patch dependencies, e.g. to address a bug in a library without having to wait for them to publish a fix.pnpm add
andpnpm install
are very similar. In general, when adding a dependency, usepnpm add
since it will only handle installs related to the new dependency.
Patching
Section titled PatchingIf 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_PACKAGE
and split yourpackage.json
file.- Your root-level
package.json
should contain only tooling related to the whole project, e.g.eslint
,prettier
,husky
, etc. - Your package-specific
package.json
should 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
pnpm
script on a specific set of workspaces with filtering (reference), e.g.pnpm --filter "abbott-bots" run build
- Doing
pnpm i
in the root level will installnode_modules
for 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
composite
set totrue
. See the documentation forcomposite
. This letstsc --build
skip 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 monoreposSuppose 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 yourbuild
command inweb
’spackage.json
- Probably make sure that your
web
package’stsconfig
doesn’t have aninclude
property.
Adding a new package to a monorepo
Section titled Adding a new package to a monorepoFor 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.json
in the new package. You can initialize one withpnpm init
. You will probably needbuild
andwatch
scripts and anexports
section, so consider copying contents from an existingpackage.json
to get those fields. - Make sure you have a
tsconfig.json
in the new package. You can typically just copy one from another part of your project.- Modify
paths
andreferences
as mentioned in this blog post so that you’re referring to any dependencies.
- Modify
- If you use
eslint
, copy over.eslintrc.cjs
so that linting will work properly. - In the new package, you should probably have an
index.ts
which can be a “barrel”. It should be in yoursrc
directory and yourtsconfig.json
should have arootDir
which containsindex.ts
. - Suppose
package-a
depends 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.json
to addcompilerOptions.paths
andreferences
.
- You would need to add this to
- Run
pnpm i
to 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 TroubleshootingERR_PNPM_REGISTRIES_MISMATCH
Section titled ERR_PNPM_REGISTRIES_MISMATCHIf you get an error like this:
…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!