Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
465 views
in Technique[技术] by (71.8m points)

node.js - How to make Grunt Deploy use global NPM modules instead of local ones

First off, I'm very new to npm and grunt. We have a project that we are using Grunt to compile and produce the output files for. I am trying to setup our build server to use Grunt to produce the output files. We are using Windows with TFS source control, and due to it's 260 character path limit, we are not able to check the grunt-bower-task module into source control (as it alone uses 230 characters in its installed path).

When I run npm install from my project directory it works fine and installs the following required modules into the node_modules folder in my project directory:

  • grunt
  • grunt-bower-task
  • grunt-contrib-compass
  • grunt-contrib-connect
  • grunt-contrib-jshint
  • grunt-contrib-requirejs
  • grunt-contrib-watch

And then when I run grunt deploy from my project directory everything works as expected.

While I could simply make running npm install part of the build process, I prefer not to, as it takes a few minutes to download all of the files, and I don't want our builds to depend on an external web service being available.

I've seen that you can install modules either locally or globally, so I'm hoping to just be able to install the modules globally on the build server so that they do not need to be in the node_modules folder directly inside the project directory before running grunt deploy. I've ran npm install -g, as well as npm install -g [module] for each of the modules listed above, as well as npm install -g grunt-cli.

If I do npm prefix -g it shows me that the global module directory is C:Users[My User]AppDataRoaming pm, and when I look in that directory's node_modules folder I do see all of the modules. However, when I run grunt deploy it complains with:

Fatal error: Unable to find local grunt

If I include just the *node_modulesgrunt* directory, then I still get these errors:

Local Npm module "grunt-contrib-watch" not found. Is it installed?

Local Npm module "grunt-contrib-jshint" not found. Is it installed?

...

I've also tried using *grunt deploy --base "C:Users[My User]AppDataRoaming pm", but it complains that it then cannot find other files, such as .jshintrc.

So is there a way that I can run grunt deploy and have it check the npm global prefix path for the modules, rather than looking in the project directory?

A hacky work around is to copy the modules manually during the build process to the local project directory, but I would like to avoid this if possible.

For reference, this is what my package.json file looks like:

{
  "name": "MyProject",
  "version": "0.0.1",
  "scripts": {
    "preinstall": "npm i -g grunt-cli bower"
  },
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-compass": "~0.2.0",
    "grunt-contrib-watch": "~0.4.4",
    "grunt-contrib-jshint": "~0.6.0",
    "grunt-contrib-requirejs": "~0.4.1",
    "grunt-contrib-connect": "~0.3.0",
    "grunt-bower-task": "~0.2.3"
  }
}

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Workaround: Explicitly list all transient dependencies in your own package.json.

Say, for example, that you depend on module_a, and that module_a depends on module_b. After npm install you'll have node_modules/module_a/node_modules/module_b/ because npm will install module_b local to module_a. However, if you add module_b as a direct dependency in your package.json (and the version specifiers match exactly), then npm will only install module_b once: at the top level.

This is because when modules are required, they start looking in the nearest node_modules directory and traverse upwards until the required module is found. So npm is able to save disk space by only installing the module at the lowest level at which the versions match.

So, revised example. You depend on module_a@0.1.0 which depends on module_b@0.2.0. If you also depend on module_b@0.1.0, you'll end up with module_b installed twice. (Version 0.1.0 will be installed at the top level, and 0.2.0 will be installed under module_a.) However, if you depend on v0.2.0 (using the exact version string in your package.json as module_a uses), then npm will notice it can use the same version of module_b. So it will only install module_b at the top level, and not under module_a.

Long story short: add whichever transient dependencies you have that have deep module trees directly to your own package.json and you'll end up with a more shallow node_modules tree.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...