简体   繁体   中英

Node doesn't install child module dependencies when version is same as parent module

Normally I'm able to discover on Google any issues I face, but in this case I have absolutely no idea what to search for.

My parent module has two dependencies:

  • "grunt-contrib-uglify": "~0.2.7"
  • "node-snapshot": "~0.3.22"

However when node-snapshot also relies on ~0.2.7 , it isn't installed in node-snapshot 's node_modules directory. My Snapshot application deploys automatically to Heroku via Travis and therefore has:

"scripts": {
  "test": "grunt test",
  "start": "node example/server/default.js",
  "postinstall": "node_modules/grunt-cli/bin/grunt build:production"
}

Which is also invoked after installing it in my parent module ( npm install node-snapshot ), but fails because both parent and child rely on grunt-contrib-uglify ~0.2.7 :

>> Local Npm module "grunt-contrib-uglify" not found. Is it installed?
Warning: Task "uglify" not found. Use --force to continue.

If the parent module relies on a different version of grunt-contrib-uglify then node-snapshot successfully installs grunt-contrib-uglify in its node_modules directory and everything is tickety-boo.

How would I go about resolving this issue? It's evident to me that all children need their own installations, even when the parent has the same module, because relatively, the sub-module ( node-snapshot ) is unable to find one of its dependencies.

After some researching last night, this is apparently a known issue with npm. There are many threads about sub-module dependencies not being installed because the parent module has satisified a particular dependency.

The following thread in particular on GitHub was very informative: https://github.com/npm/npm/issues/5001

At the moment there is no solution , but there are workarounds.

In my particular case with the postinstall the workaround was to add a preinstall with the --ignore-scripts flag which prevented the scripts hooks from being recursively invoked. This enabled npm install to run in isolation and to thus install all dependencies irrespective of parent modules.

Therefore my package.json now looks almost exactly the same, but with the preinstall hook:

"scripts": {
  "test": "grunt test",
  "start": "node example/server/default.js",
  "preinstall": "npm install --ignore-scripts",
  "postinstall": "bower install; grunt build:production"
}

npm doesn't install duplicate modules when it can help it. It also doesn't need paths for run scripts. What happens when you do:

"postinstall": "grunt build:production"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM