在Heroku上创建node.js应用程序时是否应该将node_modules检入git中?


368

我在这里遵循了Heroku上node.js的基本入门说明:

https://devcenter.heroku.com/categories/nodejs

这些指令不会告诉您创建.gitignore node_modules,因此暗示应将node_modules检入git。当我在git中包含node_modules时,我的入门应用程序正确运行。

当我遵循以下更高级的示例时:

https://devcenter.heroku.com/articles/realtime-polyglot-app-node-ruby-mongodb-socketio https://github.com/mongolab/tractorpush-server (源)

它指示我将node_modules添加到.gitignore。因此,我从git中删除了node_modules,将其添加到.gitignore中,然后重新部署。这次部署失败,如下所示:

-----> Heroku receiving push
-----> Node.js app detected
-----> Resolving engine versions
       Using Node.js version: 0.8.2
       Using npm version: 1.0.106
-----> Fetching Node.js binaries
-----> Vendoring node into slug
-----> Installing dependencies with npm
       Error: npm doesn't work with node v0.8.2
       Required: node@0.4 || 0.5 || 0.6
           at /tmp/node-npm-5iGk/bin/npm-cli.js:57:23
           at Object.<anonymous> (/tmp/node-npm-5iGk/bin/npm-cli.js:77:3)
           at Module._compile (module.js:449:26)
           at Object.Module._extensions..js (module.js:467:10)
           at Module.load (module.js:356:32)
           at Function.Module._load (module.js:312:12)
           at Module.require (module.js:362:17)
           at require (module.js:378:17)
           at Object.<anonymous> (/tmp/node-npm-5iGk/cli.js:2:1)
           at Module._compile (module.js:449:26)
       Error: npm doesn't work with node v0.8.2
       Required: node@0.4 || 0.5 || 0.6
           at /tmp/node-npm-5iGk/bin/npm-cli.js:57:23
           at Object.<anonymous> (/tmp/node-npm-5iGk/bin/npm-cli.js:77:3)
           at Module._compile (module.js:449:26)
           at Object.Module._extensions..js (module.js:467:10)
           at Module.load (module.js:356:32)
           at Function.Module._load (module.js:312:12)
           at Module.require (module.js:362:17)
           at require (module.js:378:17)
           at Object.<anonymous> (/tmp/node-npm-5iGk/cli.js:2:1)
           at Module._compile (module.js:449:26)
       Dependencies installed
-----> Discovering process types
       Procfile declares types -> mongod, redis, web
-----> Compiled slug size is 5.0MB
-----> Launching... done, v9

运行“ heroku ps”可确认崩溃。好的,没问题,所以我回滚了更改,将node_module添加回git存储库,并将其从.gitignore中删除。但是,即使还原后,在部署时我仍然会收到相同的错误消息,但是现在应用程序再次正常运行。运行“ heroku ps”会告诉我该应用程序正在运行。

所以我的问题是正确的方法是什么?是否包含node_modules?为什么回滚时仍会收到错误消息?我的猜测是git储存库在Heroku方面处于不良状态?


10
我是Heroku的Node语言所有者,答案很简单:不。不要签到node_modulesHeroku应用。
hunterloftis

@hunterloftis“不检查node_modules ”或“不检查node_modules ”?要澄清一下,作为Heroku的Node语言所有者,您是否希望我们通过git push上传整个node_modules?我宁愿不要由于带宽浪费以及Heroku将它们放在我的git push的后端上这一事实;但是,我必须手动编辑node_modules中的文件才能使Heroku加载我的应用程序。因此,我不得不忽略node_modules减去包括已编辑文件的整个模块,以使其正常工作。
ZStoneDPM

Answers:


400

第二次更新

常见问题解答不再可用。

从以下文档中shrinkwrap

如果您希望锁定软件包中包含的特定字节,例如对能够重现部署或构建有100%的信心,则应将依赖项检查到源代码控制中,或采用其他可以验证的机制内容而不是版本。

香农和史蒂芬以前曾提到过这一点,但我认为,这应该是公认的答案的一部分。


更新资料

以下建议列出的来源已更新。他们不再建议node_modules提交文件夹。

通常不会 允许npm解决软件包的依赖关系。

对于您部署的软件包,例如网站和应用程序,应使用npmrinkwrap锁定完整的依赖树:

https://docs.npmjs.com/cli/shrinkwrap


原始帖子

作为参考,npm FAQ清楚地回答了您的问题:

将node_modules检入git中以查找您部署的内容,例如网站和应用程序。不要将node_modules检入git中以查找要重用的库和模块。使用npm来管理开发环境中的依赖关系,而不要在部署脚本中。

并出于一些合理的理由,请阅读Mikeal Rogers对此的帖子


资料来源:https : //docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git


13
这是不正确的-实际上,这是一个非常糟糕的主意。如果要在Windows上进行开发,然后在Linux上进行部署,则在部署时将需要重建node_modules。这意味着-混乱。很多修改过的文件,不知道该怎么办。
user3690202 2014年

8
这是不可能的-我们的一些开发人员针对Windows进行开发,其他针对Linux进行开发,但是使用相同的代码库。最好的方法是不提交节点模块-哎呀。
user3690202 2014年

7
@ user3690202听起来您的案子非常不合常规,而不是规范,因此说“这不正确”可能是一种夸大其词。话虽如此,不确定您的确切用例是什么,但是我无法想到使用Windows和Linux进行开发的任何原因。坚持一个,并在您支持的所有平台上运行测试或质量检查。
Kostia 2014年

16
@Kostia我们的用例很常见。我们是志愿者,使用我们自己的机器,而不是公司的机器。对于开源来说,这似乎是很普遍的情况。
亚当

4
@Adam切线,您可以添加要编译的文件.gitignore吗?这样,源就在git中,而任何已编译的组件都不会,这与grunt和gulp项目中git distoutput文件夹被忽略的方式类似。
科斯蒂亚

160

检查node_modulesgit时最担心的是,在未来10年内,当您的生产应用程序仍在使用中时,npm可能就不在了。否则npm可能会损坏;或维护者可能决定从其存储库中删除您依赖的库;或者 否则您使用的版本可能会被剪裁掉。

这可以通过Maven等回购管理器来缓解,因为您始终可以使用自己的本地Nexus或Artifactory维护使用的软件包的镜像。据我了解,npm不存在这样的系统。像Bower和Jamjs这样的客户端库管理器也是如此。

如果您已将文件提交到自己的git仓库中,则可以根据需要更新它们,并且可以轻松进行可重复的构建,并且知道应用程序不会由于某些第三方操作而中断。


10
今天有很多选择:Nexus(issue.sonatype.org/browse/NEXUS-5852),Artifactory(jfrog.com/jira/browse/RTFACT-5143),npm_lazy(github.com/mixu/npm_lazy),npm-lazy-镜像(npmjs.org/package/npm-lazy-mirror)等
约翰·

4
来自npmjs常见问题的引用:“如果您对依赖npm生态系统感到疑惑,则应运行私有npm镜像或私有缓存。” 我认为这指向您所指的问题,对吗?
塔兰(Taylan)

3
一个
典型的

2
Npm不会在一夜之间消失,因此,好处与提交历史记录的不清晰性和庞大的捆绑包数量并不能很好地配对。如果某人正在构建他们认为在10年内仍将处于活动状态的应用程序,则可以合理地预期它将在此过程中获得大量维护。关于NPM中断的观点是一个更好的论点,尽管减轻风险的方法可能比承诺来源更好。
山姆P

3
如果您不提交依赖关系,即使是一个月的旅程也是很危险的(尽管最好是在单独的存储库中)。正如我在一个早晨克隆一个项目时发现的,发现软件包版本已从npm中删除。我花了半天时间来更改所有级联依赖项的版本,以使npm更新能够正常工作并再次构建。
理查德

67

你应该不包括 node_modules.gitignore(或者说应该包括 node_modules在源部署到Heroku的)。

如果 node_modules

  • 存在然后npm install将使用这些供应的库,并使用重建任何二进制依赖项npm rebuild
  • 不存在npm install必须自己获取所有依赖项,这会增加时间来进行编译。

请参阅Node.js buildpack源 这些确切步骤,

但是,原始错误似乎是npm和的版本之间不兼容node。始终根据此指南明确设置engines您的部分是一个好主意,以避免出现以下类型的情况:packages.json

{
  "name": "myapp",
  "version": "0.0.1",
  "engines": {
    "node": "0.8.x",
    "npm":  "1.1.x"
  }
}

这将确保开发人员/产品的价格均等,并减少将来发生这种情况的可能性。


感谢瑞安的帮助。那使我克服了npm版本错误,但现在在编译redis软件包时失败。错误消息是“ OSError:[Errno 2]没有这样的文件或目录:'/ Users / Jason / tastemade / tastebase / node_modules / redis-url / node_modules / redis / node_modules / hiredis / build”。似乎它使用的是来自Heroku服务器上本地框的路径。我需要添加到.gitignore中的node_modules中是否有某些文件?
杰森·格里芬

我不确定那个特定的库是怎么回事,但是在这种情况下,我会尝试从git中排除node_modules,看看是否有帮助(强制npm本身获取所有内容并确保新的构建环境)。
Ryan Daigle

@RyanDaigle npm(npmjs.org/doc/…)和heroku(devcenter.heroku.com/articles/…)推荐的最佳实践(2013年11月)是将node_modules检入git。您会更新答案吗(因为它的账单最高)?
蒂姆·迪金斯

推送到heroku时,您将获得输出“ ----->缓存node_modules目录以用于将来的构建”。这是为了缩短将来的段编译。
ph3nx 2014年

我有一个问题,即node_modules文件路径太长,无法提交。Git找不到文件。
法老王代码

22

我打算在评论后离开这个: 在Heroku上创建node.js应用程序时是否应该将node_modules检入到git中?

但是stackoverflow格式化它很奇怪。如果您没有相同的计算机,并且正在检入node_modules,请对本机扩展名执行.gitignore。我们的.gitignore看起来像:

# Ignore native extensions in the node_modules folder (things changed by npm rebuild)
node_modules/**/*.node
node_modules/**/*.o
node_modules/**/*.a
node_modules/**/*.mk
node_modules/**/*.gypi
node_modules/**/*.target
node_modules/**/.deps/
node_modules/**/build/Makefile
node_modules/**/**/build/Makefile

通过首先检查所有内容来进行测试,然后让另一个开发人员执行以下操作:

rm -rf node_modules
git checkout -- node_modules
npm rebuild
git status

确保没有文件更改。


刚刚添加了这个。解决了我的问题。Windows github不断崩溃,试图越过7000+ node_module文件:/
Batman

10

我相信 npm install不应在生产环境中运行。有几处可能出错的地方-npm中断,下载较新的依赖项(shrinkwrap似乎解决了这一问题)是其中两个。

另一方面, node_modules不应在git上提交。除了它们的大小外,包括它们在内的提交可能会分散注意力。

最好的解决方案是:npm install应该在类似于生产环境的CI环境中运行。将运行所有测试,并将创建一个包含所有依赖项的压缩发行文件。


为什么您有一个在CI上运行但又不会作为部署的一部分运行的步骤?这意味着您在两个系统之间没有奇偶校验!正如上面的答案所说的那样-提交文件夹时只需忽略本机扩展名,那样就可以解决npm中断之类的问题
Voycey

1
谢谢你的评论。我相信,在生产服务器中运行的node_modules应该从npm安装生成,而不是由开发人员提交的任何内容生成。开发人员的node_modules文件夹不一定与package.json内容匹配。
user2468170

8

我一直在使用提交node_modules文件夹和收缩包装。两种解决方案都没有使我高兴。

简而言之:提交的node_modules给存储库增加了太多的噪音。
而且shrinkwrap.json并不易于管理,并且无法保证某些收缩包装的项目会在几年内建成。

我发现Mozilla正在为其项目之一使用单独的存储库https://github.com/mozilla-b2g/gaia-node-modules

因此,很快我就可以在节点CLI工具https://github.com/bestander/npm-git-lock中实现这个想法

在每次构建之前添加
npm-git-lock --repo [git@bitbucket.org:your / dedicated / node_modules / git / repository.git]

它会计算package.json的哈希值,或者从远程仓库中检出node_modules的内容,或者,如果它是此package.json的第一个构建版本,它将进行清理npm install并将结果推送到远程仓库中。


5

对我有用的是将一个npm版本显式添加到package.json(“ npm”:“ 1.1.x”),而不是将node_modules检入git。部署起来可能会比较慢(因为它每次都会下载软件包),但是当签入它们时我无法编译这些软件包。Heroku正在寻找仅存在于我本地机器上的文件。


如果您认为我的答案是正确的,请接受吗?谢谢!
瑞安·戴格

如果仍然有待讨论,我将看一下这个stackoverflow帖子,该帖子几乎是您上面的问题的副本: stackoverflow.com/questions/11459733/… 基本上,看来惯例是签入node_modules,并且在本地管理这些模块的版本。这似乎很合理,也许最简洁的解释是: mikealrogers.com/posts/nodemodules-in-git.html 祝您好运!
warriorpostman 2012年

3

无需签入node_modules,而是为您的应用创建一个package.json文件。

package.json文件指定应用程序的依赖项。然后Heroku可以告诉npm安装所有这些依赖项。您链接到的教程包含有关package.json文件的部分。


我确实有一个package.json。它具有以下内容:{“ name”:“ node-example”,“ version”:“ 0.0.1”,“ dependencies”:{“ express”:“ 2.5.x”,“ redis-url”:“ 0.1。 0“,” mongodb“:”> = 0.9.9“},” engines“:{” node“:” 0.8.x“}}
Jason Griffin 2012年

我在本地框中创建了node_modules目录。这就是我签到的内容,然后将其删除,然后又添加回去。
杰森·格里芬

看完本教程后,似乎他们正在提交node_modules。在那种情况下,我不确定是否存在不提交node_modules的方法。抱歉
matzahboy12年

3

我正在使用此解决方案:

  1. 创建一个单独的存储库node_modules。如果您有应为特定平台构建的本机模块,则为每个平台创建单独的存储库。
  2. 使用以下命令将这些存储库附加到您的项目存储库git submodule

git submodule add .../your_project_node_modules_windows.git node_modules_windows

git submodule add .../your_project_node_modules_linux_x86_64 node_modules_linux_x86_64

  1. 创建从特定于平台的目录node_modulesnode_modules目录的链接,然后添加node_modules.gitignore
  2. 运行npm install
  3. 提交子模块存储库更改。
  4. 提交项目存储库更改。

因此,您可以轻松地node_modules在不同平台之间切换(例如,如果您正在OS X上开发并部署到Linux)。


3

来自https://web.archive.org/web/20150212165006/http://www.futurealoof.com/posts/nodemodules-in-git.html

编辑:原始链接是链接,但现在已失效。感谢@Flavio指出。

回顾一下。

  • 仅为已部署的应用程序签入node_modules,而不为您维护的可重用软件包签入。
  • 任何已编译的依赖项都应检入其源代码,而不是编译目标,并且应在部署时重建$ npm。

我最喜欢的部分:

所有将node_modules添加到您的gitignore中的人,请删除该屎,今天,这是一个我们非常乐于抛弃的时代的产物。全局模块的时代已经过去。


您链接的网站似乎已经过期,现在到处都是诈骗广告。我希望这些广告是“我们都乐于抛弃这个时代的产物”。
Flavio Copes

1
@FlavioCopes用Wayback Machine的链接更新了我的答案。
本杰明·克鲁兹耶

2

http://nodejs.org/api/modules.html

节点从当前模块的父目录开始,并添加/node_modules,并尝试从该位置加载模块。

如果在该目录中找不到它,那么它将移至父目录,依此类推,直到到达树的根目录为止。

如果您要滚动自己的应用程序专用模块,则可以将这些模块(并且仅保留那些模块)保留在应用程序的中/node_modules。并将所有其他依赖项移出父目录。

这个用例非常棒,它使您可以很好地保持为应用程序专门创建的模块,并且不会因以后可以安装的依赖关系而使应用程序混乱。


1

方案1:

一种情况:使用从npm中删除的软件包。如果所有模块都位于node_modules文件夹中,那么这对您来说就不是问题。如果在package.json中仅包含包名称,则无法再获取它。如果包裹的使用时间少于24小时,则可以轻松地将其从npm中删除。如果早于24小时,则需要与他们联系。但:

如果您与支持人员联系,他们将检查删除该版本的软件包是否会破坏其他安装。如果是这样,我们将不会将其删除。

阅读更多

因此发生这种情况的机会很低,但是存在方案2 ...


方案2:

出现这种情况的另一种情况:您开发软件的企业版或非常重要的软件,并在package.json中编写:

"dependencies": {
    "studpid-package": "~1.0.1"
}

您使用该function1(x)程序包的方法。

现在,studpid-package的开发人员将方法重命名function1(x)function2(x),他们犯了一个错误……他们将其软件包的版本从更改1.0.11.1.0。这是一个问题,因为当您npm install下次调用时,您将接受版本,1.1.0因为您使用了波浪号("studpid-package": "~1.0.1")。

调用function1(x)现在可能会导致错误和问题。


将整个node_modules文件夹(通常超过100 MB)推送到您的存储库中,将浪费您的内存空间。几kb(仅package.json)与数百MB(package.json和node_modules)相比...考虑一下。

可以做到/在以下情况下应该考虑一下

  • 该软件非常重要。

  • 发生故障时会花钱。

  • 您不信任npm注册表。npm是集中式的,理论上可以关闭。

并不需要发布文件夹中的情况下,如果99.9%的node_modules:

  • 您可以自己开发软件。

  • 您已经编写了一些程序,只想将结果发布在GitHub上,因为其他人可能对此感兴趣。


如果您不希望将node_modules放入存储库中,只需创建一个.gitignore文件并添加line即可node_modules

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.