Search code examples
node.jsnpmpatch

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 cannot update prompt-sync anymore or I might lose the changes I made (losing !== just breaking my patched changes)
  • I cannot basically run any package commands, such as npm audit fix etc, as those might also overwrite my changes
  • This doesn't work at all, if I want to have my project in a git repository, because I will obviously add node_modules to .gitignore and if anyone were to pull my repository and run npm install, it would install prompt-sync without my changes

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?


Solution

  • 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.