为什么我们需要全局和本地安装gulp?

308

关于gulp的2本手册说我需要先全局安装gulp(带-g标志),然后再本地安装一次。为什么需要这样做?


12
该项目的“入门指南”页面(https://github.com/gulpjs/gulp/blob/master/docs/getting-started.md#getting-started)也是这么说的。(也没有说明原因。) - T.J. Crowder
11
我希望npm能够使用全局安装的依赖包,且其版本号与本地包相同。每个项目目录都需要5MB的gulp内容:/ - Ciantic
@Ciantic 没有保证,但是... ➪ https://dev59.com/NoLba4cB1Zd3GeqPgZXZ#25879563 - Frank N
7个回答

250

将工具全局安装后,用户可以在命令行中的任何位置使用它,包括在 Node 项目之外。对于 Node 项目来说,全局安装是不好的,因为它会让部署变得更加困难。

npm 5.2+

npm 5.2 附带的 npx 实用程序解决了这个问题。你可以使用它调用本地安装的实用程序,就像使用全局安装的实用程序一样(但必须以npx开头)。例如,如果您想调用本地安装的 eslint,可以执行以下操作:

npx eslint .

npm < 5.2

当在您的package.json文件的script字段中使用时,npm会搜索node_modules工具以及全局安装的模块,因此本地安装就足够了。

所以,如果您满意(package.json中的内容):

"devDependencies": {
    "gulp": "3.5.2"
}
"scripts": {
    "test": "gulp test"
}

如果你使用 npm run test 运行测试,那么你就不需要全局安装了。这两种方法都很有用,可以让人们快速设置项目而不需要使用 sudo。此外,当 package.json 中的版本更新时,gulp 也会被更新,这意味着所有人在开发该项目时都将使用相同版本的 gulp。

补充说明:

似乎当全局安装 gulp 时,它会表现出一些异常行为。当作为全局安装使用时,gulp 会查找本地已安装的 gulp 并将控制权传递给它。因此,全局安装 gulp 需要先安装本地的 gulp 才能工作。然而,上述答案仍然成立:与全局安装相比,本地安装始终更可取。


3
如果没有互联网接入,你该怎么办?如果 gulp 没有全局安装,你该如何使用它? - IGRACH
3
@IGRACH 上述脚本不使用互联网连接。如果您想在不使用 package.json 中的脚本字段的情况下执行相同的操作,则可以使用 ./node_modules/.bin/gulp - qubyte
1
我已经为 gulpcoffee 定义了别名,以便从我的节点项目根目录中运行命令(例如 alias gulp="node_modules/.bin/gulp")。这样,如果需要使用这些命令,它们就很容易使用,并且不会发生全局/本地版本冲突。 - vesse
@qubyte 嗯?运行gulp时出现“找不到本地的gulp”这个问题,肯定与“为什么我们需要全局和本地安装gulp?”这个问题有关。 - Derek Greer
1
添加了一个附录。希望这样就涵盖了 gulp 的奇怪之处。 - qubyte
显示剩余13条评论

88

简而言之,这里是 为什么 我们需要全局和本地安装gulp的原因:

这种方法有效的原因是因为 gulp 尝试使用您本地安装版本的 gulpfile.js 来运行它,参见此处。因此需要全局和本地安装gulp。

基本上,当您在本地安装 gulp 时,脚本不在您的 PATH 中,因此您不能只输入 gulp 并指望shell找到该命令。通过全局安装,gulp 脚本得以进入您的 PATH,因为全局的 node/bin/ 目录很可能在您的路径中。

然而,为了尊重您的本地依赖关系,gulp 将使用您本地安装的自身版本来运行 gulpfile.js


1
~/bin是Unix中每个用户二进制文件的惯例,并且在许多操作系统上默认包含在PATH中。gulp应该能够从那里链接其二进制文件。 - mikemaccana
3
换句话说,你需要全局安装 gulp 包以便将 node_modules/.bin/gulp 放入路径中。存储空间很便宜,但为了模拟符号链接而浪费 MB 的行为在我看来是纯粹的马虎。 - ntd

82

你可以使用以下命令将全局安装的gulp链接到本地:

npm link gulp

1
我知道最好使用本地安装,但有些情况下你可能无法安装或者不想安装(比如你的专用 CI 服务器已经全局安装了 gulp,而你每次提交都要重新安装)。总之,感谢提到 npm link - gion_13
1
我看到你做的了。那很聪明。 - deepelement
这并不试图回答这个问题。 - mikemaccana
1
不,它只是使其无效。 - Berislav Lopac

72
问题“为什么我们需要在全局和本地都安装gulp?”可以分解为以下两个问题:
1.如果我已经在全局安装了gulp,为什么还需要在本地安装它?
2.如果我已经在本地安装了gulp,为什么还需要在全局安装它?
在单独回答这些问题的同时,其他人已经提供了出色的答案,但我认为将信息汇总到一个统一的答案中会更加有益。
为什么如果我已经在全局安装了gulp,还需要在本地安装?
安装本地gulp的理由包括以下几点:
1.将项目的依赖项包含在本地可确保使用的gulp版本(或其他依赖项)是最初预期的版本。
2.当使用require()时,Node不会默认考虑全局模块(您需要在脚本中包含gulp)。这主要是因为默认情况下未将全局模块的路径添加到NODE_PATH中。
3.根据Node开发团队的说法,本地模块加载速度更快。我不知道为什么,但这似乎更与node在生产中的用途(即运行时依赖项)相关,而不是开发中(即dev依赖项)。我想这是一个合理的理由,因为一些人可能关心通过加载本地和全局模块获得的任何轻微的速度优势,但是请随意对此理由表示怀疑。
为什么如果我已经在本地安装了gulp,还需要在全局安装它?
安装全局gulp的理由实际上只是方便地在系统路径中自动找到gulp可执行文件。
要避免本地安装,可以使用npm link [package],但link命令以及install --global命令似乎不支持--save-dev选项,这意味着似乎没有简单的方法来全局安装gulp,然后轻松地将其版本添加到本地package.json文件中。

我认为最终使用全局模块选项更有意义,可以避免在所有项目中重复安装常用工具,尤其是在使用grunt、gulp、jshint等开发工具的情况下。不幸的是,当你做与主流相反的事情时,你可能会遇到一些工具上的阻力。


8
你是整个互联网上第一个指出这个问题有两个方面的人,我给你点赞。大多数人都只回答“如果我已经在本地安装了gulp,为什么还需要全局安装?”而我想知道的是“如果我已经全局安装了gulp,为什么还需要在本地安装?” - Nathan J.B.
10
需要这么详细的解释才能理解这个问题,说明这种工作方式并不是非常合理。为每个项目重复安装同样的工具是没有必要的。 - Kokodoko
4
你的回答非常冷静美妙。我的回答会有80%的脏话,因为这似乎太他妈的愚蠢了。从工具的角度来看,本地安装理论可能是正确的,但从操作系统和软件包管理器的角度来看,这太疯狂了,我找不到合适的词语来形容它。NPM/gulp的开发者吸了什么毒?如果有人持不同意见,请先阅读dpkg、yum、pacman等系统软件包管理器的工作原理。 - JepZ
2
@JepZ,只有gulp表现得非常奇怪,没有任何node或npm强制执行这一点。如果gulp的开发人员经常破坏补丁版本,那么在项目中保留特定版本的gulp是有意义的,否则其他构建工具通常是全局安装的。但是,好吧,我只是来骂人的。 - Stoffe
2
现在这已经不是问题了,因为社区已经转而使用yarn :) - Derek Greer
显示剩余2条评论

8

如果您本地安装的node_modules文件夹在PATH中,则从技术上讲,您不需要全局安装它。但通常这样做并不是一个好主意。

或者,如果npm test引用了gulp,则只需输入npm test,就可以运行本地的gulp。

我从未全局安装gulp -- 我认为这样做不好。


3
比将其放在路径中更好的方法是使用NPM脚本。 - Jay

2
我不确定我们的问题是否直接与仅在本地安装gulp有关。但是我们不得不自己安装一堆依赖项。这导致了一个“庞大”的package.json文件,我们不确定仅在本地安装gulp是否真的是一个好主意。由于我们的构建环境,我们不得不这样做。但是如果没有绝对必要,我不建议不全局安装gulp。我们遇到了与以下blog-post所述类似的问题。
所有开发人员在他们的本地机器上都全局安装了gulp,因此没有出现这些问题。在构建系统上,我们遇到了上述问题。如果有人感兴趣,我可以深入探讨这个问题。但现在我只想提到仅在本地安装gulp并不是一条容易的道路。

是的,请深入探讨这个问题。 - kenorb

2

如果您使用的是MacOS或Linux操作系统,建议将以下内容添加到您的PATH环境变量中(在bashrc等文件中):

Original Answer翻译成"最初的回答"

node_modules/.bin

使用这个相对路径条目,如果你在任何节点项目的根文件夹中,可以运行任何命令行工具(如eslint、gulp等等),无需担心“全局安装”或npm run等问题。自从我使用了这个方法后,我再也没有全局安装过任何模块。"最初的回答"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接