So you’re working on an npm-based project and you’ve discovered one of your dependencies has a bug. What do you do?
The easiest thing — and I’d guess the thing most folks do — is open an issue on that package’s GitHub repository and hope the package maintainer gets around to fixing it.
But that could take a while, if it ever happens at all, and you’ve got a deadline coming up.
Fork the broken package’s repository on GitHub and push your fix to a new branch. Then update the package dependency declaration in your
package.json like this:
Now you and your teammates will all get the patched version when you do
npm install or
npm update. You can continue to maintain your fork and all the dependency management will keep working just like how you’re used to.
If you want to go through the whole process of arriving at this solution, read on…
Patch it locally!
So a dependency is broken and you can’t afford to wait for the maintainer to maybe notice and fix your issue for you. What now?
Well, you do have all the source code to the package right there in your
Of course, if you just dive into
node_modules/some-broken-package and start hacking, you might fix the problem locally, but nobody else on your team is going to get your fix. And if you’re smart, you’ll have gitignore’d
node_modules from the very start of your project, relying instead on your (checked in)
npm install for each user to sync their dependencies.
What you really need to do is get your fix into the broken package’s repository and published to npm, so when anyone else does
npm install (or
npm update) they also get your fix.
Make a pull request!
If you open up
node_modules/some-broken-package/package.json you can find some useful information.
homepage entry will (often) take you right to the package repository on GitHub:
Sometimes the homepage isn’t a GitHub URL and is instead a separate website (e.g.
some-broken-package.com). You could alternatively find the
repository section and get the actual git URL from there:
Either way, you should be able to find the package repository on GitHub (or maybe some other service; but it’ll probably be on GitHub) and fork it.
Now clone your fork — separately from your original project! — and create a branch for your patch:
git clone git+ssh://firstname.lastname@example.org/me/some-broken-package.git git checkout -b my-patch
Hop in there and make your fix(es), commit, push, and open a pull request on the original repository. And you’re done!
…except that you’re not, because your original project still needs to pick up the fix, and the whole point of this article is that you don’t want to wait for the package maintainer to accept your PR (if they ever do).
So how do you get your fix into your original project?
Copy it over into node_modules!
You could just copy over the changed files:
cp some-broken-package/lib/*.* my-project/node_modules/some-broken-project/
But that only works locally, not for your teammates, and your patch will just get silently stomped by
npm install or
npm update later anyway, so this is actually a terrible idea.
What you really want is for your
package.json to connect
some-broken-project to your fork instead of the original package.
Update your package.json!
Fortunately, you can do this easily, but if you didn’t go spelunking into the darkest depths of the npm documentation you might not’ve discovered how.
Open up your
package.json (the one for your main project, not the one for the broken package) and find the dependency entry for the broken package:
Replace the version bit with the git URL of your fork, including the name of your patch branch:
If your fork is on GitHub you can actually simplify this to just
username/repository#branch like so:
Now if you nuke
node_modules/some-broken-package and then run
npm install again you’ll see your fix come through. And that means your team members — and anyone else who clones your project — will also get your fix.
Furthermore, you can continue to make updates on your
my-patch branch, push them, and
npm update as needed.
You probably don’t want to publicly release a package that’s structured like this, as it kinda works around npm’s whole philosophy of package management, but this should work well as a temporary Band-Aid for critical issues in dependencies where you can’t afford to sit around and wait for the package maintainer to respond.
There are a couple ways this can play out in the long-term (i.e. as you approach release):
- Your PR is eventually accepted and the package maintainer publishes an update to npm. In this case, simply revert your dependency declaration in
package.json(you could just delete it and then
npm install some-broken-packageto get the new, canonical version).
- It’s time to launch and your PR still languishes in review hell. Maybe that package has even been completely abandoned! In this case you have a few options: publish your fork as an new npm package and link to that, or embed the forked version directly into your main project and don’t treat it as an npm dependency at all.
There might be better ways to handle this situation, but this is the best one I’ve found so far. I’m certainly open to alternatives!