25

I'm using node 0.10.x and npm 2.15.0, I want to forcibly exclude a nested dependency that ends up being installed.

So far I've tried to create npm-shrinkwrap.json and manually edited it to remvoe the nested dependency but after running rm -rf node_modules && npm install ... I can still see the nested dependency being built for:

[email protected] install /.../node_modules/loopback-connector-mongodb/node_modules/mongodb/node_modules/kerberos
(node-gyp rebuild) || (exit 0)
CXX(target) Release/obj.target/kerberos/lib/kerberos.o
CXX(target) Release/obj.target/kerberos/lib/worker.o
CC(target) Release/obj.target/kerberos/lib/kerberosgss.o
CC(target) Release/obj.target/kerberos/lib/base64.o
CXX(target) Release/obj.target/kerberos/lib/kerberos_context.o
SOLINK_MODULE(target) Release/kerberos.node
1

3 Answers 3

16

npm >= 8.3.0

Using the overrides feature of newer versions of npm it is now possible to prevent a dependency of a dependency from being installed by replacing it with a link to the local file system. It's a bit of a hack, but it works both on Unix and on Windows.

First, make sure that you are using npm 8.3.0 or later. Enter in the command line:

npm -v

to see the version of npm installed.

Now, looking at the example in the question, let's say one of your dependencies has installed an old version of mongodb which in turn has installed kerberos in your node_modules folder.

You don't use kerberos anyway and you don't want it to be installed by npm install, so edit the "overrides" section of your package.json file like this:

package.json

{
  ...
  "overrides": {
    "kerberos": "../_EXCLUDED_"
  },
  ...
}

Be sure to run npm install again after this change. This will create a symbolic link (Unix) or a junction (Windows):

node_modules/mongodb/node_modules/kerberos -> node_modules/mongodb/node_modules/_EXCLUDED_

It is intended that the target of the symlink does not exist: with this, every attempt to load kerberos using require or import will result an easily detectable error:

Error: Cannot find module 'kerberos'

This should save you from the pain of debugging errors caused by excluding a dependency that is required.

2
  • This doesn't seem to work. npm install just spins forever. If I specify a directory that does exist (like the path to another actually-installed dep), there is an error that the resolved dep does not match the required one.
    – Coderer
    Commented Jun 24 at 19:07
  • This strategy doesn't work properly (at least with newer npm versions). If you try to run npm i a second time without deleting package-lock.json I get the error npm error Cannot destructure property 'package' of 'node.target' as it is null., which is nasty. I'm testing the other suggested strategy but this should really be a RFE to NodeJs so it doesn't accidentally break in the future.
    – ceztko
    Commented Jun 28 at 10:07
7

Faced the same issue, and created a dummy package dry-uninstall to override unused dependencies. Use it in "overrides" section of package.lock:

{
  "overrides": {
    "kerberos": "npm:dry-uninstall"
  }
}

This is the same hack as in GOTO 0 answer, but package has empty index.js, so code will not fail on require('kerberos') or import.

1
  • 1
    This seems to work better for me than the other strategy but the package could have been named better, such as dummy-dependency or something like that. dry-uninstall naming doesn't really grasp the point of the package, IMO. Anyway, there should be official support for this future (hence a RFE should be done to NodeJs), so there's no need for workarounds like this that can break inadvertently.
    – ceztko
    Commented Jun 28 at 10:10
-1

The NPM team has provided some suggestions that may also help for situations like this. See: https://blog.npmjs.org/post/145724408060/dealing-with-problematic-dependencies-in-a

Their suggestion is, essentially, to branch or fork the dependency that is pulling in the dependency you do not want. From your code snippet, I think you want to fork the mongodb module and remove the dependency on kerberos and update loopback-connector-mongodb to use your fork of mongodb.

This answer on a similar question may be helpful when forking the dependencies: https://stackoverflow.com/a/35349284/1524989

It would also be possible to substitute a dummy package for the one you want to remove. To do so, create a new package (e.g. npm init kerberos ) and update package-lock.json (or npm-shrinkwrap.json, if you prefer) to substitute it for the real kerberos package.

0

Not the answer you're looking for? Browse other questions tagged or ask your own question.