在Heroku上创建node.js应用程序时,我应该将node_modules检入git吗?

Should I check in node_modules to git when creating a node.js app on Heroku?

我在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,然后重新部署。这次部署失败如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
-----> 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: [email protected] || 0.5 || 0.6
           at /tmp/node-npm-5iGk/bin/npm-cli.js:57:23
           at Object. (/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. (/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: [email protected] || 0.5 || 0.6
           at /tmp/node-npm-5iGk/bin/npm-cli.js:57:23
           at Object. (/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. (/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?为什么我回滚时仍然会收到错误消息?我的猜测是Heroku方面的git存储库处于不良状态?


第二次更新

常见问题解答不再可用。

shrinkwrap的文档:

If you wish to lock down the specific bytes included in a package, for example to have 100% confidence in being able to reproduce a deployment or build, then you ought to check your dependencies into source control, or pursue some other mechanism that can verify contents rather than versions.

Shannon和Steven之前曾提到这一点,但我认为,它应该是公认答案的一部分。

更新

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

Usually, no. Allow npm to resolve dependencies for your packages.

For packages you deploy, such as websites and apps, you should use npm
shrinkwrap to lock down your full dependency tree:

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

原帖

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

Check node_modules into git for things you deploy, such as websites
and apps. Do not check node_modules into git for libraries and modules
intended to be reused. Use npm to manage dependencies in your dev
environment, but not in your deployment scripts.

对于一些很好的理由,请阅读迈克尔罗杰斯的帖子。

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


我最大的担心是不检查node_modules进入git是10年后,当你的生产应用程序仍在使用时,npm可能不在身边。或者npm可能会被破坏;或者维护者可能决定从他们的存储库中删除您依赖的库;或者您使用的版本可能会被删除。

这可以通过像maven这样的repo管理器来缓解,因为您可以随时使用自己的本地Nexus或Artifactory来维护镜像,使用您使用的软件包。据我所知,npm不存在这样的系统。对于像Bower和Jamjs这样的客户端库管理器也是如此。

如果您已将文件提交到您自己的git仓库,那么您可以在需要时更新它们,并且您可以获得可重复构建的舒适度以及您的应用程序因某些第三方操作而不会中断的知识。


您不应在.gitignore中包含node_modules(或者您应该在部署到Heroku的源中包含node_modules)。

如果node_modules

  • 然后npm install将使用那些出售的libs并将使用npm rebuild重建任何二进制依赖项。
  • 然后npm install将不得不获取所有依赖项本身,这为slug编译步骤增加了时间。

有关这些确切的步骤,请参阅Node.js buildpack源代码

但是,原始错误看起来是npmnode版本之间的不兼容性。根据本指南始终明确设置packages.jsonengines部分是个好主意,以避免出现以下类型的情况:

1
2
3
4
5
6
7
8
{
 "name":"myapp",
 "version":"0.0.1",
 "engines": {
   "node":"0.8.x",
   "npm": "1.1.x"
  }
}

这将确保dev / prod奇偶校验并减少将来出现此类情况的可能性。


在这个评论之后我打算离开这个:在Heroku上创建node.js应用程序时,我应该在node_modules中检查git吗?

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

1
2
3
4
5
6
7
8
9
10
# 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

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

1
2
3
4
rm -rf node_modules
git checkout -- node_modules
npm rebuild
git status

确保没有更改文件。


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

另一方面,node_modules不应该在git上提交。除了他们的大尺寸,包括他们在内的承诺可能会分散注意力。

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


我一直在使用提交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 [[email protected]:your / dedicated / node_modules / git / repository.git]

它将计算你的package.json的哈希值,并将从远程仓库检出node_modules内容,或者,如果它是这个package.json的第一个版本,将执行干净的npm install并将结果推送到远程仓库。


对我有用的是明确地将一个npm版本添加到package.json("npm":"1.1.x")而不是将node_modules检入git。它的部署速度可能较慢(因为它每次都会下载软件包),但是在签入时我无法编译软件包.Heroku正在查找仅存在于本地文件夹中的文件。


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

  • 创建包含node_modules的单独存储库。如果您具有应为特定平台构建的本机模块,则为每个平台创建单独的存储库。
  • 使用git submodule将这些存储库附加到项目存储库:
  • <5233>

    git submodule add .../your_project_node_modules_linux_x86_64 node_modules_linux_x86_64

  • 创建从特定于平台的node_modulesnode_modules目录的链接,并将node_modules添加到.gitignore
  • 运行npm install
  • 提交子模块存储库更改。
  • 提交项目存储库更改。
  • 因此,您可以在不同平台上轻松切换node_modules(例如,如果您在OS X上进行开发并部署到Linux)。


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

    编辑:原始链接是这个,但它现在已经死了。谢谢@Flavio指出它。

    To recap.

    • Only checkin node_modules for applications you deploy, not reusable
      packages you maintain.
    • Any compiled dependencies should have their
      source checked in, not the compile targets, and should $ npm rebuild
      on deploy.

    我最喜欢的部分:

    All you people who added node_modules to your gitignore, remove that
    shit, today, it’s an artifact of an era we’re all too happy to leave
    behind. The era of global modules is dead.


    而不是检入node_modules,为您的应用程序创建一个package.json文件。

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


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

    [...] node starts at the parent directory of the current module, and adds /node_modules, and attempts to load the module from that location.

    If it is not found there, then it moves to the parent directory, and so on, until the root of the tree is reached.

    如果您正在推出自己的应用程序模块,那么您可以将这些(并且只有那些)保存在应用程序的/node_modules中。并将所有其他依赖项移出到父目录。

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


    方案1:

    一种情况:
    您使用从npm删除的包。
    如果你有node_modules文件夹中的所有模块,那么对你来说不会有问题。
    如果你只在package.json中有包名,你就不能再得了它。
    如果包裹不到24小时,您可以轻松地从npm中删除它。
    如果它超过24小时,那么您需要联系他们。
    但:

    If you contact support, they will check to see if removing that version of your package would break any other installs. If so, we will not remove it.

    阅读更多

    因此,这种可能性很低,但有情景2 ......

    方案2:

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

    1
    2
    3
    "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)推送到存储库,将花费您的内存空间。
    几个kb(仅限package.json)与数百MB(package.json和node_modules)进行比较......想一想。

    你可以这样做/应该考虑如果:

    • 该软件非常重要。

    • 当事情失败时,你会花钱。

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

    如果出现以下情况,则无需在99.9%的情况下发布node_modules文件夹:

    • 你只是为自己开发一个软件。

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

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