【发布时间】:2013-08-10 08:00:09
【问题描述】:
我想知道我们是否应该在我们的 repo 中跟踪 node_modules 或者在检查代码时执行 npm install?
【问题讨论】:
标签: git node.js version-control npm
我想知道我们是否应该在我们的 repo 中跟踪 node_modules 或者在检查代码时执行 npm install?
【问题讨论】:
标签: git node.js version-control npm
答案不像Alberto Zaccagni suggests那么简单。如果您开发应用程序(尤其是企业应用程序),在您的 git 存储库中包含 node_modules 是一个可行的选择,您选择哪种替代方案取决于您的项目。
因为他对 node_modules 的争论非常好,所以我将专注于他们的论点。
假设您刚刚完成了企业应用程序,您将不得不支持它 3-5 年。你绝对不想依赖别人的 npm 模块,因为它明天就会消失,你不能再更新你的应用了。
或者您的私有模块无法从 Internet 访问,并且您无法在 Internet 上构建您的应用程序。或者您可能出于某种原因不想依赖最终构建在 npm 服务上。
你可以找到优缺点in this Addy Osmani article(虽然是关于鲍尔的,但情况几乎一样)。最后我将引用 Bower 主页和 Addy 的文章:
“如果您编写的包不是打算供其他人使用(例如,您正在构建一个 Web 应用程序),则应始终将已安装的包检查到源代码管理中。”
【讨论】:
git checkout foo。如果 node_modules 不在 VCS 下 - 切换分支是 git checkout foo ; npm install 并且您当前的 NPM 版本需要工作;)
模块详细信息存储在packages.json,这就足够了。无需签到node_modules。
人们过去常常将node_modules 存储在版本控制中以锁定模块的依赖关系,但现在不再需要npm shrinkwrap。
这一点的另一个理由,正如@ChrisCM 在评论中所写:
另外值得注意的是,任何涉及本机扩展的模块都无法在架构间工作,需要重新构建。提供不将它们包含在 repo 中的具体理由。
【讨论】:
我建议不要签入 node_modules,因为例如 PhantomJS 和 node-sass 等软件包会为当前系统安装适当的二进制文件。
这意味着如果一个开发者在 Linux 上运行 npm install 并签入 node_modules - 它不适用于另一个在 Windows 上克隆 repo 的开发者。
最好检查 npm install 下载的 tarball 并将 npm-shrinkwrap.json 指向它们。您可以使用 shrinkpack 自动执行此过程。
【讨论】:
npm install --global shrinkpack 本身是否不具有延迟的弱点,通过要求其他软件包来安装缩小的软件包?这违背了艾迪的建议。
shrinkpack 才能可靠地安装构建依赖项。因此,构建工具的安装本身成为反对将所有构建依赖项提交给版本控制的论点的弱点。
这个话题很老了,我明白了。但是由于 npm 生态系统的情况发生了变化,我错过了对此处提供的参数的一些更新。
我总是建议不要将 node_modules 置于版本控制之下。到目前为止,在已接受答案的上下文中列出的这样做的几乎所有好处都已经过时了。
已发布的包不能再轻易地从 npm 注册表中撤销。因此,您不必担心失去项目之前依赖的依赖项。
将 package-json.lock 文件放入 VCS 有助于处理频繁更新的依赖项,尽管依赖于相同的 package.json 文件,但可能会导致不同的设置。
因此,如果有离线构建工具,将 node_modules 放入 VCS 可能被认为是唯一符合条件的用例。但是,node_modules 通常会增长得很快。任何更新都会改变很多文件。这正在以不同的方式影响存储库。如果您真的考虑到长期影响,那也可能是一个障碍。
像 svn 这样的集中式 VCS 需要通过网络传输已提交和已签出的文件,这在签出或更新 node_modules 文件夹时会非常缓慢。
当涉及到 git 时,如此大量的附加文件会立即污染存储库。请记住,git 不会跟踪任何文件版本之间的差异,而是会在单个字符发生更改时立即存储文件的任一版本的副本。对任何依赖项的每次更新都会导致另一个大型变更集。由于这会影响备份和远程同步,您的 git 存储库将迅速变大。如果您决定稍后从 git 存储库中删除 node_modules,由于历史原因,它仍然是其中的一部分。如果您已将 git 存储库分发到某个远程服务器(例如用于备份),那么清理它是您将遇到的另一项痛苦且容易出错的任务。
因此,如果您关心高效的流程并希望保持“小”,我宁愿使用单独的工件存储库,例如 Nexos 存储库(或只是一些带有 ZIP 存档的 HTTP 服务器),提供一些以前获取的依赖项集下载。
【讨论】:
不使用源代码控制跟踪 node_modules 是正确的选择,因为某些 NodeJS 模块,如 MongoDB NodeJS 驱动程序,使用 NodeJS C++ 附加组件。这些附加组件是在运行npm install 命令时编译的。因此,当您跟踪node_modules 目录时,您可能会不小心提交特定于操作系统的二进制文件。
【讨论】:
我同意ivoszz 的观点,即有时很有用检查 node_modules 文件夹,但是...
场景 1:
一种情况: 您使用从 npm 中删除的包。 如果您在 node_modules 文件夹中拥有所有模块,那么这对您来说不是问题。 如果你在 package.json 中只有包名,你就不能再得到它了。 如果一个包的使用时间少于 24 小时,您可以轻松地将其从 npm 中删除。 如果它超过 24 小时,那么您需要联系他们。 但是:
如果您联系支持人员,他们会检查删除该版本的软件包是否会破坏任何其他安装。如果是这样,我们不会删除它。
所以发生这种情况的可能性很小,但是有第二种情况......
场景 2:
这种情况的另一种情况: 你开发一个企业版的软件或者一个非常重要的软件,并写在你的 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)推送到您的存储库会占用您的内存空间。 几 kb(仅 package.json)与数百 MB(package.json 和 node_modules)相比......想想吧。
您可以做到/应该考虑一下如果:
软件很重要。
发生故障时会花钱。
您不信任 npm 注册表。 npm 是中心化的,理论上可以关闭。
如果出现以下情况,您不需要在 99.9% 的情况下发布 node_modules 文件夹:
您只为自己开发软件。
您已经编写了一些程序,只是想在 GitHub 上发布结果,因为其他人可能会对它感兴趣。
如果您不希望 node_modules 出现在您的存储库中,只需创建一个 .gitignore 文件并添加行 node_modules。
【讨论】:
npm install 可能会在某些包中生成不同的文件(依赖于操作系统的文件)。但我不确定。有人可以验证这是真的吗?
package-lock.json 的原因。如果将来更新 studpid-package 出现问题,您可以回滚锁定文件以找出适合您的确切版本。
我想提供一个中间的选择。
node_modules。package-lock.json 文件确定您的依赖版本。在极少数情况下,您无法访问 NPM(或您使用的其他注册表)或 NPM 中的特定包,您拥有 node_modules 的副本并且可以继续工作,直到您恢复访问权限。
【讨论】:
package-lock.json 仅出现在更高版本中。也许 NodeJS 的早期实现者当时没有这种方法。
还有一点需要考虑:签入node_modules 使得使用dependencies 和devDependencies 之间的区别变得更加困难/不可能。
但另一方面,可以说将经过测试的完全相同的代码推送到生产环境是令人放心的 - 所以包括devDependencies。
【讨论】:
如果 package.json 中提到了依赖项,则不需要签入 node_modules。任何其他程序员都可以通过执行 npm install 来简单地获得它,并且 npm 足够聪明,可以在您的项目工作目录中创建 node_modules。
【讨论】: