从另一个文件夹访问 node_modules

12

最近开始使用Gulp,我无法确定是否真的有必要在当前项目文件夹中直接拥有node_modules的副本?例如,我的目录结构如下:

mysite
└─builder
      └──node_modules
└─work
└─work2

如何在不复制它的情况下从'work'或'work2'文件夹中访问'builder'文件夹中的node_modules?它相当大,大约100mb,我觉得为每个新项目都复制它没有意义。

我尝试了在package.json文件中添加这一行export NODE_PATH='D:\OpenServer\domains\mysite\build',然后运行命令gulp,但是它回复了以下内容:
[10:24:27] Local gulp not found in d:\OpenServer\domains\mysite\work [10:24:27] Try running: npm install gulp


2
为什么你把node_modules放在builder里面?为什么不直接放在我的网站(mysite)里面? - Eduardo Yáñez Parareda
@Eduardo Yáñez Parareda 嗯,我不知道搜索 node_modules 的逻辑是如何进行的。如果我知道它也会在父目录中搜索...但访问邻居目录/.. 是个问题。好吧,现在我会这样做了。 - Julia
1
它从当前脚本开始向上遍历路径,直到找到 node_modules/ 目录 - 如果在到达根目录时该目录不存在,则失败。require() 还接受一个路径,该路径以 .// 开头。在这种情况下,它将其视为文件路径。请记住,NPM 和 Node.js 是两个独立的系统。node_modules/ 约定是 Node.js 的事情,而 package.json 约定是 NPM 的事情。 - Qix - MONICA WAS MISTREATED
1
这也是 Github 上 NPM 仓库的持续讨论。虽然目前所有内容都被复制,但在您的主目录中有一个模块缓存。我认为,应该从该目录创建符号链接,这是一个常数时间操作。但是 NPM 的所有者似乎不同意 :) - Qix - MONICA WAS MISTREATED
https://dev59.com/zVwY5IYBdhLWcg3wwp84#40573740 - w411 3
显示剩余2条评论
5个回答

5

简短回答

不要这样做。让 NPM 按设计的方式工作即可。然而,为了节省空间,您可以在当前处于休眠状态的项目上删除 node_modules 文件夹,并在切换回这些项目时,使用一次 npm install 即可重新创建它。


理由说明

即使您分享 node_modules,它仍然可能存在冗余。接下来你会怎么做?

复制模块是 NPM 的本质。如果您深入到 node_modules 文件夹树中,您可能会注意到它甚至可以在一个给定的依赖树下包含同一库的多个副本。假设您明确请求了两个模块,并且这两个模块本身都拉取了一个处理很多事情的依赖项,因此被称为lib_DADDYMUMMY

node_modules
    + a_module_you_use v0.5
        + lib_DADDYMUMMY v0.1 (pulled as a dependency of this module)
    + another_module_that_you_requested v0.3
        + lib_DADDYMUMMY v0.1 (again ! pulled as a dependency of this other module)

当您的两个模块需要不同版本的lib_DADDYMUMMY时,这将非常方便。当您维护长期项目时,这将非常方便!在JavaScript世界中,由于API变化快速,您可以认为大多数像样的项目都是长期存在的。:)

有人可以想象,所有依赖项都是共享的,位于一个平坦的结构中,具有库的几个版本相邻,每个人都可以在那里找到自己需要的内容。该存储库可以称为.m2。但是遗憾的是,NPM就是不这么工作。

NPM认为存储空间很便宜。这是其帮助您管理依赖关系版本、依赖关系的依赖关系和依赖关系的依赖关系的价格。当workwork2的生命周期不断延长时,我认为这是照顾它们的艰苦工作的一个合理价格。我不会试图通过强制使用半Maven式的文件夹模型来阻止它。


2
谢谢 :) 是的,我明白。可能各种复杂的项目需要为每个项目拥有自己的节点模块。但是我大多数时候需要在几个前端项目中运行类似的Gulp任务,例如编译Sass,优化图像,将几个文件合并成一个等等...难道不是更好地共享一个node_modules给所有这些相似的项目吗? - Julia
一开始就是这样的。如果你的项目都有相同的结构,并且始终保持不变,那么它将是这样的。 但是,如果workwork2在非常不同的源代码树中合并文件,并且一年后work2已经得到维护并使用了新的SaSS功能,而work则依赖于当你编写它时还可以的指令,但是SaSS团队决定这些指令已经过时,那么你将会遇到麻烦,并面临很多不必要的维护开销。 :) - Mathias Dolidon
1
谢谢,但这个解决方案对我来说不是最好的... :) 因为 npm install 需要很长时间。如果我只需要在一个文件中进行小改动,那么这样做就不值得了。我在这里看到很多警告,不要为几个项目共享一个 node_modules... 但我会尝试 :D 好吧,如果将来遇到麻烦,那就是我不应该这么固执的经验 :D 但现在对我来说,这似乎是快速访问类似项目和创建新项目的最佳解决方案。 - Julia
固执是一种品质,直到一个人变得过于固执。 ;) 保重! - Mathias Dolidon
每次将100MB复制到另一个文件夹或花费10分钟从头开始安装都是浪费空间/时间。 - user2401543

1
也许你应该把你的package.json放到根目录下(mysite/package.json),
然后尝试在根目录上安装node_modules。
此外,你需要在同一目录下编写gulpfile。
mysite  
|- package.json  
|- node_modules  
|- gulpfile.js  
└─builder  
└─work  
└─work2

然而,我建议您为每个项目编写一个单独的gulpfile。

谢谢。现在对我来说越来越清晰了。我认为我情况的最佳解决方案是将 node_modules 放入 mysite 中,然后创建 mysite 的子目录,每个子目录都有自己的 package.json 和 gulpfile.js。 - Julia

1
由于版本问题,您不应该这样做。如果您的模块需要同一软件包的不同版本,则会遇到问题。一个软件包将获胜,并可能破坏另一个软件包。
此外,您还需要以某种方式合并依赖项列表 - 这意味着您需要从 `work/package.json`,`work2/package.json` 等获取依赖项,然后一次性安装所有依赖项。
合并 `node_modules/` 也无法解决问题 - 相信我,不要尝试。

好的,但是至少当两个项目都需要相同的模块时,为什么不给它们两个都提供相同的模块文件夹呢? - Julia
@Julia 因为这很难管理。这两个模块中的第二个需要另一个依赖项,package.json 分歧。 - Qix - MONICA WAS MISTREATED

0

I.

使用pnpm - 一个npm的替代品。

它通过只有一份所有包的副本,并在所有其他文件夹中进行符号链接来解决您的问题。

这也使它更快,允许不同版本的依赖项(例如,您可以有两个版本的underscore),更安全一些(因为恶意软件包无法扫描您的其他软件包)等等。

它还可以用于管理不同的Node版本,并设置全局包而不使用sudo。

II.

您可以使用相对或绝对路径到其他文件夹,如:

const path = require('node:path');
const modules = path.join(__dirname, '../otherfolder/node_modules');
require(`${modules}/mypkg`); 
III.

另外,NPM还可以使用npm link [<package-spec>]来设置符号链接,请参见此处,或者您也可以使用操作系统命令 [ln -s ...]。


0
node_modules文件夹粘贴到您的mySite目录中。
所有npm包,如gulp,都可以在您的workwork2目录中使用。
但是,现在(您的文件夹结构)工作文件夹无法在其父目录中找到node_modules

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