ChatGPT解决这个技术问题 Extra ChatGPT

在 Heroku 上创建 Node.js 应用程序时,我应该将文件夹“node_modules”签入 Git 吗?

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

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

这些指令没有告诉您创建 .gitignore node_modules,因此暗示应该将文件夹 node_modules 签入到 Git。当我在 Git 存储库中包含 node_modules 时,我的入门应用程序运行正常。

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

使用 Node.js、Ruby、MongoDB 和 Socket.IO 构建实时的多语言应用程序

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 方面的状态不佳。

我是 Heroku 的 Node 语言所有者,答案很简单:不。不要将 node_modules 签入 Heroku 应用程序。
@hunterloftis'不要将node_modules签入'或'不要将node_modules签入'?澄清一下,作为 Heroku 的 Node 语言所有者,您是否希望我们通过 git push 上传整个 node_modules?由于带宽浪费以及 Heroku 会将它们放在我的 git push 的后端,我不想这样做;但是,我必须手动编辑我的 node_modules 中的文件才能让 Heroku 加载我的应用程序。因此,我不得不忽略 node_modules 减去包含我编辑的文件的整个模块才能让它工作。

J
Josh Correia

第二次更新

常见问题解答不再可用。

shrinkwrap 的文档中:

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

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

更新

以下建议 has been updated 列出的来源。他们不再建议提交 node_modules 文件夹。

通常,没有。允许 npm 为您的包解析依赖项。对于您部署的包,例如网站和应用程序,您应该使用 npm shrinkwrap 锁定您的完整依赖关系树:https://docs.npmjs.com/cli/shrinkwrap

原帖

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

将 node_modules 检入 git 以获取您部署的内容,例如网站和应用程序。不要将 node_modules 签入 git 以获取打算重用的库和模块。使用 npm 管理开发环境中的依赖项,而不是部署脚本中的依赖项。

要了解这方面的一些充分理由,请阅读 Mikeal Rogers' post on this

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


这是不正确的——事实上这是一个非常糟糕的主意。如果您是在 Windows 上开发然后在 Linux 上部署,则需要在部署时重新构建 node_modules。这意味着 - 混乱。修改了很多文件,不知道该怎么办。
这是不可能的——我们的一些开发人员开发了针对 Windows 的开发人员,其他开发人员针对 Linux 开发了相同的代码库。最好的方法是不提交节点模块 - 哎呀。
@user3690202 听起来您有一个非常规的案例,而不是规范,所以说“这不正确”可能是夸大其词。话虽如此,不确定您的确切用例是什么,但我想不出同时使用 windows 和 linux 进行开发的任何理由。坚持一个,并在您支持的所有平台上运行测试或 QA。
@Kostia 我们的用例很常见。我们是志愿者,使用我们自己的机器,而不是公司的机器。对于开源来说,这似乎是一种很常见的情况。
@Adam 切线,您可以将正在编译的文件添加到 .gitignore 吗?这样,源代码在 git 中,而任何已编译的组件都不在,类似于在 grunt 和 gulp 项目中 gitignored distoutput 文件夹的方式。
P
Peter Mortensen

对于不将文件夹 node_modules 检入 Git,我最大的担忧是 10 年后,当您的生产应用程序仍在使用时,npm 可能不会出现。或者 npm 可能会损坏;或者维护人员可能决定从他们的存储库中删除您依赖的库;或者您使用的版本可能会被删减。

这可以通过 Maven 等存储库管理器来缓解,因为您始终可以使用自己的本地 Nexus (Sonatype) 或 Artifactory 来维护您使用的软件包的镜像。据我了解,npm 不存在这样的系统。对于像 BowerJam.js 这样的客户端库管理器也是如此。

如果您已将文件提交到自己的 Git 存储库,那么您可以随时更新它们,并且您可以舒适地进行可重复构建,并且知道您的应用程序不会因为某些第三方操作而中断。


今天有很多选择:Nexus (issues.sonatype.org/browse/NEXUS-5852)、Artifactory (jfrog.com/jira/browse/RTFACT-5143)、npm_lazy (github.com/mixu/npm_lazy)、npm-lazy-mirror (npmjs.org/package/npm-lazy-mirror) 等。
引自 npmjs 常见问题解答:“如果您对依赖 npm 生态系统感到偏执,您应该运行私有 npm 镜像或私有缓存。”。我认为这指向您所指的问题,对吗?
Npm 不会在一夜之间消失,所以它的好处并不能与你的提交历史的清晰性和你巨大的包大小相匹配。如果有人正在构建一个他们认为在 10 年后仍然有效的应用程序,那么可以合理地预期它会在此过程中得到大量维护。不过,关于 NPM 中断的观点是一个更好的论点,尽管可能有比承诺采购更好的方法来减轻这种风险。
如果您不提交您的依赖项(最好在单独的存储库中),那么即使是一个月后也是危险的。一天早上,当我克隆我的一个项目并发现一个包版本已从 npm 中删除时,我发现了这一点。我花了半天时间更改所有版本的级联依赖项,以使 npm update 能够正常工作并再次构建。
P
Peter Mortensen

您不应该在 .gitignore 文件中包含文件夹 node_modules(或者更确切地说you should include folder node_modules in your source部署到 Heroku)。

如果文件夹 node_modules:

如果存在,则 npm install 将使用那些供应商的库,并将使用 npm rebuild 重建任何二进制依赖项。

不存在,那么 npm install 将不得不自己获取所有依赖项,这会增加 slug 编译步骤的时间。

请参阅 these exact steps 的 Node.js buildpack 源代码。

但是,最初的错误看起来是 npm 和 Node.js 版本之间的不兼容。最好始终根据 this guide 明确设置 packages.json 文件的 engines 部分,以避免这些类型的情况:

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

这将确保development/production parity并减少将来出现此类情况的可能性。


感谢瑞恩的帮助。这让我克服了 npm 版本错误,但现在在编译 redis 包时它失败了。错误消息是“OSError: [Errno 2] No such file or directory: '/Users/Jason/tastemade/tastebase/node_modules/redis-url/node_modules/redis/node_modules/hiredis/build'”。看起来它正在使用来自 heroku 服务器上我本地盒子的路径。 node_modules 中是否有某些文件需要添加到 .gitignore?
我不确定该特定库发生了什么,但在这种情况下,我会尝试从 git 中排除 node_modules 并查看是否有帮助(强制 npm 自行获取所有内容并确保新的构建环境)。
@RyanDaigle npm (npmjs.org/doc/…) 和 heroku (devcenter.heroku.com/articles/…) 推荐的最佳实践现在(2013 年 11 月)是将 node_modules 签入 git。你会更新你的答案(因为它有最高的账单)吗?
推送到 heroku 时,您将获得输出“-----> 缓存 node_modules 目录以供将来构建”。这是为了缩短未来的 slug 编译。
我有一个问题,node_modules 文件路径太长而无法提交。 Git 找不到文件。
P
Peter Mortensen

发表此评论后,我打算离开:Should I check in folder "node_modules" to Git when creating a Node.js app on Heroku?

但是 Stack Overflow 的格式很奇怪。

如果您没有相同的机器并且正在检查 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 文件时崩溃:/
P
Peter Mortensen

我认为 npm install 不应该在生产环境中运行。有几件事可能出错 - npm 中断、下载较新的依赖项(shrinkwrap 似乎已经解决了这个问题)是其中两个。

另一方面,不应将文件夹 node_modules 提交给 Git。除了它们的大尺寸之外,包括它们在内的提交可能会分散注意力。

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


为什么在 CI 上运行的步骤不会作为部署的一部分运行?这意味着您在 2 个系统之间没有对等性!正如上面的答案所说 - 提交文件夹只是忽略本机扩展,这样你就可以应对 npm 中断等问题
谢谢你的评论。我相信在您的生产服务器中运行的 node_modules 应该从 npm 安装生成,而不是从开发人员提交的任何内容生成。开发人员的 node_modules 文件夹不一定与 package.json 内容匹配。
P
Peter Mortensen

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

简而言之:一个提交的 node_modules 文件夹给存储库增加了太多的噪音。而且 shrinkwrap.json 不容易管理,并且不能保证一些收缩包装的项目将在几年内构建。

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

所以我很快就在 Node.js 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 并将结果推送到远程存储库。


P
Peter Mortensen

将 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祝你好运!
P
Peter Mortensen

不要签入文件夹 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" } }
我在本地机器上创建了 node_modules 目录。这就是我签入的内容,然后删除,然后又添加回来。
在查看了更多教程之后,似乎他们正在提交 node_modules。在那种情况下,我不确定是否有办法不提交 node_modules。对不起
P
Peter Mortensen

来自 "node_modules" in Git

回顾一下。仅为您部署的应用程序签入 node_modules,而不是您维护的可重用包。任何编译的依赖项都应该签入它们的源,而不是编译目标,并且应该在部署时 $ npm rebuild。

我最喜欢的部分:

所有在你的 gitignore 中添加 node_modules 的人,去掉那个狗屎,今天,它是一个时代的产物,我们都乐于把它抛在后面。全局模块的时代已经结束。

(原来的链接是 this one,但现在已失效。感谢@Flavio 指出。)*


您链接的网站似乎已经过期,现在充满了诈骗广告。我希望这些广告是“我们都乐于留下的时代的产物”。
@FlavioCopes 使用来自 Wayback Machine 的链接更新了我的答案。
P
Peter Mortensen

我正在使用这个解决方案:

创建一个包含文件夹 node_modules 的单独存储库。如果您有应为特定平台构建的本机模块,则为每个平台创建一个单独的存储库。使用 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 创建从特定于平台的 node_modules 到 node_modules 目录的链接,并将 node_modules 添加到 .gitignore。运行 npm 安装。提交子模块存储库更改。提交您的项目存储库更改。

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


P
Peter Mortensen

场景一:

一种情况:

您使用从 npm 中删除的包。如果您在 node_modules 文件夹中拥有所有模块,那么这对您来说不是问题。如果你在 package.json 中只有包名,你就不能再得到它了。

如果一个包的使用时间少于 24 小时,您可以轻松地将其从 npm 中删除。如果它超过 24 小时,那么您需要联系他们。

但:

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

read more

所以这种情况的可能性很低,但有第二种情况......

场景二:

这种情况的另一种情况:

你开发一个企业版的软件或一个非常重要的软件,并在你的 package.json 中写:

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

您使用该软件包的function1(x)方法。

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

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

将整个 node_modules 文件夹(通常超过 100 MB)推送到您的存储库,将占用您的内存空间。与数百 MB(package.json 和 node_modules)相比,只有几 kb(仅 package.json)……想想看。

如果出现以下情况,您可以这样做/应该考虑一下:

软件非常重要。

当某些事情失败时,它会花费你的钱。

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

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

您只为自己开发软件。

你已经编写了一些程序,只是想在 GitHub 上发布结果,因为其他人可能会对它感兴趣。

如果您不希望 node_modules 出现在您的存储库中,只需创建一个 .gitignore 文件并添加行 node_modules


l
laggingreflex

如果您正在滚动您自己的特定于您的应用程序的模块,您可以:

将这些(并且只有那些)保留在应用程序的 /node_modules 文件夹中,并将所有其他依赖项移出到父 ../node_modules 文件夹。这将起作用,因为 NodeJS CommonJS 模块系统如何通过向上移动到父目录等方式工作,直到到达树的根目录。见:https://nodejs.org/api/modules.html

或者 gitignore 所有 /node_modules/* 除了你的 /node_modules/your-modules。请参阅:使 .gitignore 忽略除少数文件之外的所有内容

这个用例非常棒。它使您可以很好地保留您专门为您的应用程序创建的模块,并且不会与可以稍后安装的依赖项混淆。