npm安装很多依赖项

10
我最近购买了一个 HTML 模板,其中包含许多插件放在 bower_components 目录和 package.js 文件中。我想安装另一个我喜欢的包,但决定使用 npm 进行此操作。 当我键入: npc install pnotify node_modules 目录被创建,并包含约 900 个其他包的目录。 这些是什么?为什么他们随我的包一起安装了?我进行了一些研究,结果发现它们是必需的,但是我真的需要将数百个不必要的包交付给生产环境吗?

1
当然需要,几乎每个安装的软件包都使用其他软件包,而每个软件包又使用其他软件包,以此类推。 - alexmac
1
@alexmac 我不明白这个,因为我的模板没有它们也能正常工作,所以我真的不明白它的意义。 - RA.
pnotify 使用了 4 个包:https://github.com/sciactive/pnotify/blob/master/package.json#L18。 - alexmac
仍然是4而不是900。它们的大小超过40MB,因此我仍然不明白在生产中传递超过40MB的不必要数据的意义... - RA.
是的,有4个,但它们每个都有自己的依赖项。在您的项目根目录中运行npm ls,它将显示已安装软件包的列表。 - alexmac
1
我为这个寻求规范答案的问题添加了悬赏,只是为了澄清事情。数百MB重的数百个软件包传递给一个几KB的项目有什么意义呢? - Cyclone
6个回答

6
这是一个非常好的问题。我想指出几点。
V8引擎、Node模块(依赖项)以及“requiring”它们:
Node.js是建立在V8引擎上的,而V8引擎是用C++编写的。这意味着Node.js的依赖项基本上都是用C++编写的。
现在,当您需要一个依赖项时,您实际上需要从C++程序或js库中获取代码/函数,因为这就是新库/依赖项的制作方式。
库有很多函数,您不会使用所有函数
例如,看看 express-validator module,它包含了很多函数。当您需要该模块时,您是否会使用它提供的所有功能?答案是否定的。人们通常只需使用其中一个单一的好处来要求这些软件包,尽管所有的函数最终都被下载下来,这浪费了不必要的空间。
将由其他节点依赖项制作的节点依赖项视为解释型语言
例如,JavaScript是用C/C++编写的,其功能和编译器最初也是用汇编语言编写的。可以将其视为一棵树。每次创建新分支都是为了更方便的使用,最重要的是为了节省时间,使事情更快。同样,当人们创建新的依赖关系时,他们使用/需要已经存在的依赖关系,而不是重写整个C++程序或js脚本,因为这样做会使一切变得更容易。
当创建新的NPMs时需要其他依赖关系时,问题就出现了。当依赖项的作者从各处获取其他依赖项来使用其中少量的好处时,他们最终会下载所有这些依赖项(他们并不真正关心它们的大小,因为他们大多数情况下并不担心大小,或者他们宁愿这样做,而不是明确地编写新的依赖项或C++附加组件),这将占用额外的空间。例如,您可以通过访问此链接this link.查看express-validator模块使用的依赖项。
因此,当您有使用大量依赖项的大型项目时,最终会占用很多空间。

解决方法

方案一

需要一些Node.js专家。为了减少下载的软件包数量,专业的Node.js开发人员可以进入模块保存的目录,打开javascript文件,查看它们的源代码,并删除他们不使用的函数,而不改变包的结构。

方案二(不值得花时间)

您也可以创建自己的个人依赖项,这些依赖项是用C++编写的,或者更好地使用js编写,这将根据程序员而定,实际上占用最少的空间,但会浪费最多的时间,以减小大小而不是完成工作。(注意:大多数依赖项都是用js编写的。)

方案三(常见)

与使用方案二相反,您可以实现WebPack

结论和注释

基本上,无法避免下载所有的节点包,但如果您相信自己能够做到,可以使用解决方案1,这也有可能破坏依赖关系的整体意图(因此请将其个性化并仅用于特定目的)。或者只需利用像WebPack这样的模块。此外,请问自己:这些包真的会给您带来问题吗?

1
我认为OP谈论的是JavaScript依赖项,而不是C++插件。解决方案1也不是一个好主意,因为它破坏了整个包管理的理念。一些有趣的阅读材料:正面反面 - TGrif
很好的答案。但是我仍然不太明白为什么npm要这样做。这并没有简化事情。你可以拿Python和它的包作为例子,这些包是通过pipeasy_install安装的。当你需要一个特定的包时,你只需要输入pip install package,你就能得到这个包了,这个包可能有数百个其他包的依赖,但是你需要自己提供它们,否则在运行脚本时会提示缺少包。对于JavaScript也可以这样做(并在缺少某个东西时进行控制台提示)。 - RA.
针对你的最后一个问题,根据文件语法的不同可能需要一些工作,但是你可以将所有变量export到一个文件中,并将该文件链接到你的HTML文件中。至于第一个问题,是的,这只是它的一个缺点。@DonaldDuck - Ahmed Can Unbay
@turmuka 我听说使用 bower 包管理器(扁平包树)可以更好地完成这项工作。但我不确定,因为我已经购买了使用 npm 的模板。我在某个地方读到过,使用 NPM 也可以将几个脚本捆绑成一个 - 你有关于这方面的知识吗? - RA.
2
如果在重新分发时大小成为问题,可以选择选项3。Node.Js是JavaScript,因此它也可以与类似webpack的东西一起打包。虽然webpack不经常用于node.js,但它可以与之配合使用。如果可能的话,可以应用tree-shaking等技术,从而大大减小您的dist大小。 - Keith
显示剩余18条评论

0

这是一个很老的问题,但我碰巧遇到了非常相似的情况,就像RA所指出的那样。

我尝试使用vscode框架来工作,并在尝试使用npm init -y安装npm时,它生成了许多不同的依赖项。在我的情况下,是在运行npm init -y之前添加的vscode扩展ESlint

  • 卸载ESlint
  • 重新启动vscode以应用该卸载
  • 删除先前生成的package.jsonnode-modules文件夹
  • 再次执行npm init -y

这解决了我开始使用如此多依赖项的问题。


0

然而,当您需要证明所有npm模块的许可证时,这也会产生另一个副作用...因此,当由于依赖关系而有数百个npm模块时,这项工作也变得更加繁琐。


0
这些是什么?为什么它们随我的软件包一起安装了?
依赖项的存在是为了通过模块化促进代码重用。
我需要在生产中使用数百个不必要的软件包来交付我的模板吗?
我们不应该轻易地忽略这种模块化。如果您内联您的require并消除死代码,您将失去自动应用于您的代码的依赖项维护补丁的好处。您应该将其视为一种编译,因为...嗯...它就是编译
尽管如此,如果您有权以这种编译形式重新分发所有依赖项,那么您会很高兴地了解到这些优化是由一个将JavaScript编译为JavaScript的编译器执行的。 Closure Compiler,作为我偶然发现的第一个例子,似乎执行高级编译,这意味着您可以获得死代码删除函数内联...这看起来很有前途!

0

不,如果你只是想添加一些模板,就没有必要在你的项目中添加大约900个包依赖。但这取决于你自己!

一个模板的重量并不会对node.js生态系统或其主要包系统npm造成挑战。

事实上,javascript社区倾向于制作最小可能的模块来负责一个任务,仅此而已。我想这并不是一件坏事。但这可能会导致你的项目中有很多依赖项。

现在,硬盘内存很便宜,没人再关心制作高效/小型应用程序了。

像往常一样,这只是一个选择问题。


0
交付数百MB重的包来处理几KB项目有什么意义呢?
其实没有。
如果您打算将其提供给其他开发人员,只需在共享包中gitignore(或删除)node_modules或bower_components目录。开发人员只需根据需要重新安装依赖项即可;)
如果它只是一些简单的HTML模板或类似的东西,那么Node很可能只是为了让您作为开发人员更轻松地提供实时重新加载、编译/转换typescript/babel/SCSS/SASS/LESS/Coffee等等(列表还很长;P)等等。
在这种情况下,依赖关系很可能只是dev_dependencies,并且在生产环境中根本不需要;)
此外,许多软件包都带有单独的生产和开发依赖项,因此您只需要安装生产依赖项...
npm install --only=prod

如果你的项目需要在生产环境中使用许多项目,而你真的非常希望避免这些麻烦,那么就花一些时间,并包含你的项目所需的CSS / JS文件(这可能是一个费力的任务)。


更新

生产环境与默认安装

大多数项目具有不同的开发和生产依赖项。

开发依赖可能包括SASS、typescript等编译器,uglify(代码压缩),甚至像实时刷新等东西。

而生产版本将不会包含这些内容,从而减小了node_modules目录的大小。

**没有node_modules**

在一些html模板项目中,您可能不需要在生产中使用任何node_modules,因此可以跳过执行npm install

无法访问node_modules

或者在某些情况下,当用于服务的服务器本身存在于node_modules中时,可能会阻止对其进行访问(因为没有必要从前端访问它们)。


当我使用开发依赖项而不是默认依赖项时,会有什么变化?它们各自有优势吗?我认为在两种情况下,最终都会得到相同的结果-创建文件夹并充斥着大量库。另一方面,当查看一些声称使用npm的网站时,它们的页面上没有package.json-这就是问题所在。有些人只是阻止访问它或者...将其删除以供生产使用?这实际上是一个很好的问题,阻止访问它是否合理?我想我只是太在意了;-) - RA.
1
@DonaldDuck 当你在packageA的根目录下,输入npm install命令时,将会从packageApackage.json文件中安装所有的dependenciesdevDependencies。如果你输入npm install -s packageB命令,则只会安装packageB的常规dependencies,以供packageA使用。使用devDependencies来构建模块所需的内容,使用dependencies来使用模块所需的内容。 - skylize

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