如何使Grunt Deploy使用全局NPM模块而不是本地模块

首先,我对npm和grunt很新。 我们有一个项目,我们正在使用Grunt来编译和生成输出文件。 我试图设置我们的生成服务器使用Grunt生成输出文件。 我们正在使用Windows与TFS源代码控制,并由于它的260个字符的path限制 ,我们无法检查到源代码pipe理( 因为它单独使用230个字符安装path )的grunt-bower-task模块。

当我从我的项目目录运行npm install时 ,它工作正常,并将以下必需模块安装到我的项目目录中的node_modules文件夹中:

  • 咕噜
  • 咕噜鲍尔任务
  • 咕噜-的contrib罗盘
  • 咕噜-的contrib-CONNECT
  • 咕噜-的contrib-jshint
  • 咕噜-的contrib-requirejs
  • 咕噜-的contrib手表

然后当我从我的项目目录运行grunt部署一切都按预期工作。

虽然我可以简单地使运行npm install构build过程的一部分,但我不愿意,因为它需要几分钟时间才能下载所有文件,而且我不希望我们的构build依赖于可用的外部Web服务。

我已经看到, 您可以在本地或全局安装模块 ,所以我希望能够在生成服务器上全局安装模块,以便它们不需要直接在项目目录内的node_modules文件夹中运行grunt部署 。 我已经运行了npm install -g ,以及上面列出的每个模块的npm install -g [module] ,以及npm install -g grunt-cli

如果我做npm前缀-g,它会告诉我全局模块目录是C:\ Users [我的用户] \ AppData \ Roaming \ npm ,当我查看该目录的node_modules文件夹时,我看到所有的模块。 但是,当我运行grunt部署它抱怨:

致命错误:无法find本地咕噜声

如果我只包含* node_modules \ grunt *目录,那么我仍然得到这些错误:

没有find本地Npm模块“grunt-contrib-watch”。 是否安装?

未find本地Npm模块“grunt-contrib-jshint”。 是否安装?

我也尝试过使用* grunt deploy –base“C:\ Users [我的用户] \ AppData \ Roaming \ npm”,但是它却抱怨它找不到其他文件,比如.jshintrc。

那么是否有一种方法可以运行grunt deploy ,并让它检查模块的npm全局前缀path,而不是查看项目目录?

一个黑客的解决办法是在构build过程中手动将模块复制到本地项目目录,但是我希望尽可能避免这种情况。

作为参考,这是我的package.json文件看起来像:

{ "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" } } 

谢谢。

而不是使用npm的全局选项,你应该使用模块上的符号链接来获得相似的结果。

全局npm安装只是为了方便jshintgrunt-cli等命令行工具。

解决方法:明确列出您自己的package.json中的所有临时依赖项。

比如说,你依赖于module_a,而module_a依赖于module_b。 npm install之后,你将有node_modules/module_a/node_modules/module_b/因为npm会将module_b本地安装到module_a。 但是,如果您在package.json中添加module_b作为直接依赖项(并且版本说明符完全匹配),那么npm将只安装一次module_b:位于顶层。

这是因为当需要模块时,它们开始查看最近的node_modules目录并向上遍历,直到find所需的模块。 所以npm能够通过在模块匹配的最低级别安装模块来节省磁盘空间。

所以,修改后的例子。 您依赖于依赖于module_b@0.2.0的module_a@0.1.0。 如果你也依赖于module_b@0.1.0,你最终会安装两次module_b。 (版本0.1.0将安装在顶层,0.2.0将安装在module_a下)。但是,如果您依赖于v0.2.0(在package.json中使用确切的版本string作为module_a使用),那么npm会注意到它可以使用相同版本的module_b。 所以它只会在顶层安装module_b,而不会在module_a下安装。

长话短说:将具有较深模块树的暂时依赖关系直接添加到您自己的package.json中,最后得到一个更浅的node_modules树。

我使用窗口来解决Windows上的这类问题。 即使它适用于Git,如果您在Team Explorer中使用Visual Studio中的Git集成,即使您的node_modules文件夹中存在长文件path,它也会崩溃 – 即使您没有将该文件夹添加到源代码pipe理中。

通常Grunt和Bower依赖结构导致这种情况。

  1. 我build议的第一件事是在你的软件包上运行npm dedupe 。 这是做什么的,是扫描你已经安装的软件包,看看是否有一些依赖关系是重复的。 如果在更高的层次上发现,它将删除深度testing的。

  2. 其次,如果重复数据删除无法解决问题,如果您可以find导致此问题的嵌套深度的依赖关系,请尝试将其直接安装到解决scheme中,然后再次运行重复数据删除。

  3. 如果有更多的软件包依赖性导致这种情况,那么有限责任公司将解决这个问题。 加上它非常酷,因为你可以把它挂在你的npm install上,它会在安装新的包后运行。 另外,它是完全可逆的。

我希望这有帮助。

我知道这个线程是旧的,但我终于find了自己的个人答案,使用Mac,但我认为可以说与PC完成。

跟进bevacqua的回答:

而不是使用npm的全局选项,你应该使用模块上的符号链接来获得相似的结果。

全局npm安装只是为了方便jshint或grunt-cli等命令行工具。

我做了一些挖掘,可能会给予更多的澄清:

我结束了在我的用户目录的根目录中创build一个全局文件夹。 在那个目录中,我使用npm install添加了我需要的所有软件包。 因此,例如,我运行了npm install gruntnpm install grunt-contrib-watchnpm install grunt-contrib-less等等。你也可以在同一个文件夹中添加一个package.json文件,然后运行npm install将它们全部添加到一旦。 现在我的全局目录具有以下结构:

 .global_grunt_modules node_modules grunt grunt-contrib-watch grunt-contrib-less 

然后我去了任何需要运行grunt的工作项目目录,并在该文件夹的根目录下运行命令:

ln -s ~/.global_grunt_modules/node_modules .

-s (符号链接)标志中有两个参数:

[source_file] [target_dir]

所以命令基本上说:“从我的全局node_modules文件夹创build一个符号链接,并将其链接到我的当前目录”。 的. 指定当前的工作目录。

希望这有帮助,我也遇到了麻烦。 然后,每当我有一个项目需要一个新的grunt模块,我只需要通过我的全局目录来安装它,然后在任何地方都可以创build符号链接。

当npm链接不够好(networking文件系统,…)时,可以使用'requireg'包。 这是以某种方式使其“内置”的唯一清洁解决scheme。 'requireg'包有一个函数globalize,这使得后续的require调用也在全局寻找。