Skip Navigation

Scott Spence

Patching packages with pnpm patch

3 min read

I’m currently looking into upgrading a large app where I’m working, to upgrade from Svelte 4 to Svelte 5. The upgrade from 4-5 wasn’t as much of a problem as I thought it would be, there was one issue with another Svelte package that I discovered I could patch.

In the past if I’ve needed to patch a package I’ve used patch-package, which I’ve detailed here previously with Patching Packages with patch-package.

The drawback with using patch-package is, there’s the initial install of the package then adding in a postinstall script to run the patch. With pnpm this is built into the package manager.

Patch a package with pnpm patch

So, it’s pretty straightforward but I got a bit lost after the initial command. 😅

To patch a package with pnpm you first need to specify the package and the version you want to patch.

Ok, say I want to patch the svead package to include an alt attribute on the <meta> tag.

The version installed is 0.0.4 so I’ll use that in the command:

pnpm patch [email protected]

That gives the following output:

You can now edit the following folder: /tmp/ff5c69981b5e3c7d541f32db5546a177

Once you're done with your changes, run "pnpm patch-commit '/tmp/ff5c69981b5e3c7d541f32db5546a177'"

So, this was the bit that initially confused me as I was looking the the tmp folder in the project and not my filesystem. 😅

Anyway, simplest way I found was to use VS Code to open the folder:

code /tmp/ff5c69981b5e3c7d541f32db5546a177

That opens up the folder in VS Code, I can then edit the file and commit the changes.

So, in this contrived example I want to add an alt attribute to the existing package, so I’ll add in the following code:

  <meta property="og:url" content={url} />
  <meta property="og:type" content="website" />
  <meta property="og:title" content={title} />
  <meta property="og:description" content={description} />
  <meta property="og:image" content={image} />
+ <meta property="og:image:alt" content={description} />

Then as detailed in the initial patch command I can run the commit command:

pnpm patch-commit '/tmp/ff5c69981b5e3c7d541f32db5546a177'

Now the project that has the svead package installed will now have a patches folder in the root of the project with the patch file svead+0.0.4.patch.

Taking a quick look at that details the changes made to the package:

diff --git a/components/head.svelte b/components/head.svelte
index e932bbf1ffa795c081292bc669640f75d434ebfc..a63aef8c4beab3aec901ffd6a07ace0e0db845d8 100644
--- a/components/head.svelte
+++ b/components/head.svelte
@@ -44,6 +44,7 @@ export let paymentPointer = ''; // Web Monetisation Payment pointer
 		<meta property="og:title" content={title} />
 		<meta property="og:description" content={description} />
 		<meta property="og:image" content={image} />
+		<meta property="og:image:alt" content={description} />
 	{/if}

In the package.json there’s been a pnpm section added with a patchedDependencies object. This is where the patch file is referenced.

"pnpm": {
  "patchedDependencies": {
    "[email protected]": "patches/[email protected]"
  }
}

Now I can commit that and get on with my day! 🥳

patch-remove

If the svead package gets updated in the future I can use the patch-remove command to remove the patch:

pnpm patch-remove [email protected]

If the changes I made still need to be applied then I can go through the same process as before for the new version.

Conclusion

Using pnpm for patching packages removes the need for additional tools like patch-package and postinstall scripts and automates the application of patches during the installation.

This approach helps with maintainability but also contributes to a more efficient development workflow, especially in complex projects or monorepos.

There's a reactions leaderboard you can check out too.

Copyright © 2017 - 2024 - All rights reserved Scott Spence