Swiffy
Swiffy

Reputation: 4693

What is the proper way to "patch" a node_modules module?

Say I have a Node.js app, lets call it patched-app. This app is a simple app that uses prompt-sync to ask for user input and then does something with it.

So we create a folder patched-app and initialize it with npm init. We then run npm i prompt-sync and create a new file called index.js where my code would be. To make things a little bit more interesting, I will also create a git repository here and this is the result:

+---patched-app
|   |   .gitattributes
|   |   .gitattributes
|   |   .gitignore
|   |   index.js
|   |   package-lock.json
|   |   package.json
|   |   
|   +---node_modules
|   |   |   .package-lock.json
|   |   |   
|   |   +---ansi-regex
|   |   |       index.js
|   |   |       license
|   |   |       package.json
|   |   |       readme.md
|   |   |       
|   |   +---prompt-sync
|   |   |       index.js
|   |   |       LICENSE
|   |   |       package.json
|   |   |       README.md
|   |   |       test.js
|   |   |       
|   |   \---strip-ansi
|   |           index.d.ts
|   |           index.js
|   |           license
|   |           package.json
|   |           readme.md
|   \---.git
|      <<git stuff>>

Now the issue here is that I don't like something with this prompt-sync package and so I want to edit node_modules/prompt-sync/index.js and change it to my liking. I don't necessarily want to create a whole new module such as prompt-sync-swiffy (or do I?), as my changes are small enough so I don't have to download any new packages for prompt-sync, so I'm good with the existing dependencies of ansi-regex and strip-ansi.

I could just open up node_modules/prompt-sync/index.js, edit it and be done - and that's what I have pretty much been doing thus far because I don't know any better. I have recognized at least three major issues with this though:

I also don't necessarily want to fork prompt-sync and / or create a new "official" NPM package. What I want is a method that allows me or anyone else to run npm install normally, while somehow keeping my patches to modules local e.g. have a module_patches folder which isn't ignored by the repository.

It is OK if a newer version of prompt-sync breaks my patch. That would be on me to update the patch or use a locked in version of prompt-sync.

So what are my options?

Upvotes: 14

Views: 23399

Answers (3)

Nagev
Nagev

Reputation: 13255

Assuming you've made the changes to node_modules/some-package already and have a working app.

  1. Clean the build. Crucial step! Had skipped this before and ended up with a big patch that generated strange build errors. For example, in a React Native project I do this with:
rm -rf android/build
  1. Create and enable the patch. Follow these steps from the patch-package documentation:
# run patch-package to create a .patch file
npx patch-package some-package

# commit the patch file to share the fix with your team
git add patches/some-package+3.14.15.patch
git commit -m "fix brokenFile.js in some-package"

Patches created by patch-package are automatically and gracefully applied when you use npm(>=5) or yarn.

Setup

In package.json:

 "scripts": {
+  "postinstall": "patch-package"
 }

And run:

npm i patch-package
  1. Commit package*.json files and test by removing node_modules and rebuilding.

Upvotes: 1

Eduardo Lucio
Eduardo Lucio

Reputation: 2477

Patch a "node_modules" (Node.js) module

Patch-package lets app authors instantly make and keep fixes to npm dependencies. It's a vital band-aid for those of us living on the bleeding edge.

Process

Fix a bug in one of your dependencies

MODEL

nano "node_modules/<PACKAGE_NAME>/some_file.js"

Run patch-package to create a "*.patch" (in "patches" folder) file

MODEL

npx patch-package "<PACKAGE_NAME>"

Required settings/resources in your "package.json"

For patches to be applied during installation, these settings/resources are necessary in your "package.json".

  [...]
  "dependencies": {
    [...]
    "patch-package": "X.X.X",
    "postinstall-postinstall": "X.X.X",
    [...]
  },
  [...]
  "scripts": {
    [...]
    "postinstall": "patch-package"
  },
  [...]

Ref(s):

Thanks! 😘

Upvotes: 10

Andrei
Andrei

Reputation: 4617

A nice way to patch NPM packages is using patch-package. It will automatically create patch files of your changes and apply them in postinstall hook.

Upvotes: 23

Related Questions