npm 安装许多依赖项

Posted

技术标签:

【中文标题】npm 安装许多依赖项【英文标题】:npm installs many dependencies 【发布时间】:2018-01-17 18:27:47 【问题描述】:

我最近买了一个html模板,里面有很多插件放在bower_components目录和一个package.js文件里面。我想安装另一个我喜欢的软件包,但决定为此使用npm

当我输入时:

npc install pnotify

node_modules 已创建,其中包含大约 900 个目录以及其他包。

那些是什么?为什么它们与我的软件包一起安装?我做了一些研究,结果发现这些都是必需的,但真的,我是否需要在生产环境中交付我的模板以及数百个不必要的包?

【问题讨论】:

当然你需要,几乎每个安装的包都使用了一些其他的包,并且每个包都使用了其他的包,等等。 @alexmac 我不明白,因为我的模板在没有它们的情况下工作正常,所以我真的不明白这一点。 pnotify 使用 4 个包:github.com/sciactive/pnotify/blob/master/package.json#L18。 仍然是 4 而不是 900。它们的重量超过 40 mb,所以我仍然不明白在生产中提供超过 40mb 的不必要数据... 我为这个寻求规范的答案添加了赏金,只是为了解决问题。为几个 kB 的项目交付数百个重达数百 MB 的包有什么意义。 【参考方案1】:

不,仅仅因为你想添加一些模板,就在你的项目中添加大约 900 个包依赖项是没有意义的。但这取决于你!

模板的重量并没有挑战 node.js 生态系统,也没有挑战他的主要包系统 npm。

事实上,javascript 社区倾向于使尽可能小的模块负责一项任务,而且只负责一项。 我想这不是一件坏事。但这可能是由于您的项目中有很多依赖项。

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

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

【讨论】:

【参考方案2】:

这是一个很好的问题,有几点我想指出。

V8 引擎、Node Modules(dependencies) 和 require ing它们

Node.JS 建立在 V8 引擎之上,它的源代码是 C++。这意味着 Node.JS 的依赖项基本上是用 C++ 编写的。

现在,当您 require 获取依赖项时,您正在从 c++ 程序或 js 库中删除代码/函数。这就是库/依赖项的制作方式。

图书馆有很多你不会使用的功能

例如,看看 express-validator module。它在那里有很多功能。当您需要该模块时,您是否使用了它提供的所有功能?答案是。人们需要这样的软件包只是为了使用它的一个好处,并且所有功能最终都被下载,这占用了不必要的空间。

将由其他节点依赖构成的节点依赖视为解释语言

示例: Javascript 是用 C/C++ 语言编写的,这些语言是用汇编语言编写的。把它想象成一棵树。您每次都创建新分支以更方便地使用,最重要的是,节省时间。它使事情更快。这与创建新依赖项的情况类似,当人们创建一个新的依赖项时,他们使用 (require) 已经存在的依赖项,而不是编写整个 C++ 程序或 JS 脚本,因为这会使一切变得更容易。

需要其他 NPM 来创建新 NPM 时出现问题

当依赖项的作者需要其他依赖项只是为了使用它们的一些(少量)好处时,他们最终会全部下载它们,(他们并不真正关心,因为它们大多不要担心大小,否则他们宁愿这样做而不是显式编写新的依赖项或 C++ 插件),这会占用额外的空间。例如你可以看到 express-validator 模块使用的依赖 from this link.

因此,当您拥有使用大量依赖项的大型项目时,您最终会为它们占用大量空间。

解决方法

1号

这需要一些 Node.JS 方面的专家。为了减少下载包的数量,专业的 Node.JS 开发人员可以到模块所在的目录,打开 javascript 文件,查看其源代码,并删除他们不会使用的功能而不更改包的结构。

第二名(很可能不值得你花时间)

您还可以创建您自己的个人依赖项,这些依赖项是用 C++ 或更优选 JS 编写的,这实际上会占用尽可能少的空间,具体取决于程序员,但会花费最多的时间效率低下的时间减少一些尺寸而不是做工作。 (注:大部分依赖都是用JS写的)

3 号(普通)

您可以实现 WebPack ,而不是使用选项号 2。

结论&&说明

所以基本上没有逃避下载所有节点包,但如果你相信你可以做到,你可以使用解决方案 1,这也有可能搞砸依赖的整个意图。(所以 make它是个人的并用于特定目的)或只是使用 WebPack 之类的模块。

另外,问问自己这个问题,这些包真的会给你带来麻烦吗?

【讨论】:

我认为 OP 谈论的是 JavaScript 依赖项,而不是 C++ 插件。解决方案 1 也不是一个好主意,因为它打破了包管理的整个理念。一些有趣的阅读:pro & con。 我想详细解释一切,解决方案 1 是可能的,但不是一个好主意,你是对的。只是想展示复杂/好东西。 @TGrif 不错的答案。但是,我仍然不明白为什么 npm 会这样做。这并不是在简化事情。作为示例,您可以使用 Python 及其通过 pipeasy_install 安装的软件包。当您需要某个包时,您键入pip install package 并且您就拥有了这个包,该包可能具有数百个其他包的依赖项,但由您来交付它们,否则在运行脚本时会提示您缺少包。 Javascript 也可以这样做(并在缺少某些内容时发出控制台提示)。 另一个问题是当您使用带有一些带有资产的主题系统的 php 框架时。基本上所有资产都应该存储在一个目录/assets/js 中。现在谈到使用 npm,这是一个问题。对于通过 npm 安装的每个文件,您需要一个“特殊”路径(我的意思是您在 HTML 中包含的路径,例如 <script src=".."></script>)。这只是它的另一个缺点。也许它可以以某种方式编译/移动,但我不知道。 有一个选项 3,如果大小是重新分发的问题.. Node.Js 是 javascript,因此它也可以用 webpack 之类的东西打包。 Webpack 不常用于 node.js,但它可以与它一起使用。如果可能的话,可以应用 tree-shaking 等,大大减少你的 dist 大小。【参考方案3】:

为几个 kB 的项目交付数百个重达数百 MB 的包有什么意义。

没有..

如果您打算将其提供给其他开发人员,只需 gitignore(或从共享包中删除)node_modulesbower_components 目录。开发人员只需根据需要再次安装依赖项;)

如果它像 HTML 模板或类似的东西一样简单,node 很可能只是为了让您作为开发人员的生活更轻松,提供实时重新加载、编译/转换 typescript/babel/SCSS/SASS/LESS/Coffee ...(列表继续;P)等等。

在这种情况下,依赖关系很可能只是 dev_dependencies,在生产环境中根本不需要;)

还有很多包都带有单独的生产和开发依赖,所以你只需要安装生产依赖...

npm install --only=prod

如果您的项目在生产中确实需要许多项目,并且您真的很想避免这些东西,只需花一些时间并包含您的项目需要的 css/js 文件(这可能是一项费力的任务)。


更新

生产与默认安装

大多数项目都有不同的开发和生产依赖关系,

开发依赖项可能包括诸如 SASS、typescript 等编译器、uglifiers(缩小)之类的东西,也可能包括诸如实时重载之类的东西。

生产版本不会有那些减少node_modules目录大小的东西。

** 没有node_modules**

在某些 html 模板类型的项目中,您可能在生产中不需要任何 node_modules,因此您可以跳过 npm install

无法访问node_modules

或者在某些情况下,当服务的服务器存在于 node_modules 本身时,对其的访问可能会被阻止(因为不需要从前端访问这些)。

【讨论】:

当我使用 dev 依赖项而不是默认依赖项时会发生什么变化?每个人都有另一个优点吗?我认为在这两种情况下,我都会以相同的结果结束 - 文件夹被创建并充斥着大量的库。另一方面,当查看一些声称使用 npm 的网站时,他们的页面上没有 package.json - 就是这样。有些只是阻止访问它或......将其删除以进行生产?这实际上是一个很好的问题,是否合理地阻止访问它?我想我只是太在乎了 ;-) @DonaldDuck 在packageA 的根目录下,如果你输入npm install,那么dependenciesdevDependencies 都是从package.jsonpackageA 安装的。如果您键入npm install -s packageB,则只会安装packageB 中的常规dependencies 以供packageA 使用。将devDependencies 用于构建 模块所需的东西,dependencies 用于使用 模块所需的东西。【参考方案4】:

那些是什么?为什么它们与我的软件包一起安装?

存在依赖关系是为了通过模块化促进代码重用。

...我是否需要在生产环境中交付包含数百个不必要包的模板?

人们不应该这么快就放弃这种模块化。如果您内联 requires 并消除死代码,您将失去维护补丁的好处,因为依赖项会自动应用于您的代码。您应该将其视为编译的一种形式,因为...嗯...它是编译

尽管如此,如果您获得许可以这种已编译 形式重新分发所有依赖项,您会很高兴得知这些优化是由将 Javascript 编译为 Javascript 的编译器执行的。 The Closure Compiler,作为我偶然发现的第一个示例,似乎执行advanced compilation,这意味着您将获得死代码删除函数内联...这看起来很有希望!

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

非常老的问题,但正如RA 指出的那样,我碰巧遇到了非常相似的情况。

我尝试使用 vscode 使用 node.js 框架,而当我尝试使用 npm init -y 安装 start npm 时,它生成了许多不同的依赖项。在我的例子中,我在运行 npm init -y 之前添加了 vscode 扩展 ESlint

正在卸载ESlint 重新启动 vscode 以应用该卸载 删除了之前生成的 package.jsonnode-modules 文件夹 再次npm init -y

这解决了我一开始就有这么多依赖项的问题。

【讨论】:

以上是关于npm 安装许多依赖项的主要内容,如果未能解决你的问题,请参考以下文章

如何强制 npm 3 安装嵌套依赖项?

如何安装 NPM 拒绝安装的依赖项?

NPM 仅安装后依赖项

通过 package.json 安装“全局”npm 依赖项 [重复]

npm install 不显示已安装的依赖项

无法在 Windows 10 上安装 NPM 依赖项