Nodejs最恶劣的设计,就是node_modules了

Nodejs最恶劣的设计,就是node_modules了

一个项目,某个模块的副本可能超过10个,太浪费空间了:(

34 回复

Node.js 最恶劣的设计,就是 node_modules

引言

Node.js 的 node_modules 文件夹是一个用于存放项目依赖库的地方。尽管它为开发者带来了极大的便利,但不可否认的是,它也带来了一些问题。本文将探讨 node_modules 的一些缺点,并通过具体的例子来说明这些问题。

问题描述

一个典型的 Node.js 项目可能会包含多个依赖库,这些依赖库又可能有各自的依赖库。结果就是,node_modules 文件夹中可能会出现大量的重复模块副本。例如:

my-project/
├── node_modules/
│   ├── express/
│   │   └── (express 模块文件)
│   ├── @types/
│   │   └── express/
│   │       └── (类型定义文件)
│   ├── typescript/
│   │   └── (typescript 模块文件)
│   ├── lodash/
│   │   └── (lodash 模块文件)
│   └── @types/
│       └── lodash/
│           └── (类型定义文件)
└── package.json

在这个例子中,@types/express@types/lodash 是 TypeScript 类型定义文件,它们分别依赖于 expresslodash。因此,这些依赖库及其子依赖库会被下载到 node_modules 文件夹中,导致大量重复的文件副本。

空间浪费

这种冗余的依赖库副本会导致显著的空间浪费。对于大型项目,node_modules 文件夹可能会占用几十甚至几百兆的空间。这不仅增加了项目的体积,还可能导致开发环境的磁盘空间不足。

du -sh my-project/node_modules
# 输出: 523M my-project/node_modules

性能影响

除了空间浪费之外,大量的依赖库还会增加项目的构建时间和启动时间。每次安装或更新依赖库时,都需要解析和下载所有相关的子依赖库,这无疑会拖慢整个过程。

// 安装依赖库的时间
const installTime = require('time-it'); // 假设有一个这样的库可以测量时间
installTime(() => {
    require('npm').load({}, () => {
        require('npm').install();
    });
});

结论

虽然 node_modules 为 Node.js 项目带来了极大的便利性,但其带来的空间浪费和性能影响也不可忽视。为了优化这些问题,可以考虑使用诸如 yarnpnpm 这样的包管理工具,它们提供了更高效的依赖管理方式,如依赖扁平化和依赖缓存机制,从而减少冗余的依赖库副本。

参考资料


这个设计是有必要的, 不同的模块依赖的版本可能不相同。

是个问题。

你因为模块多 服务器内存不够用了?

1楼正解。 另外node的模块一般都不大,多个副本也占不不了多少空间,相对于减少依赖的复杂度来说,这点浪费应该是值得的。

“一个项目,某个模块的副本可能超过10个”

你这明显不会写package么

还有,如果你只是发布单个模块,文件里不应该带node_modules,而应该通过package.json指明你的依赖。 这样别人的node_modules文件里会自动加入依赖。

这个反而是Node.js的优势……

加载模块还有缓存机制,所以性能上也不会因为模块多导致慢

Node.js 一个很不错的设计…在你眼里成了恶劣…目测应该是洁癖党…再说了…冗余点空间…比到时候各种版本冲突好不能太多了…

这样我看没啥问题。

每次不用重复加载,有缓存吧

这个绝对是node.js的优势,这样做非常好,各个项目依赖的包版本号可能不相同,很好的独立各个项目,不像Python为了这个功能还需要搞一个 VirtualEnv 来管理各个项目的依赖包版本,node.js原生支持还不满足?

之前bower拉取bootstrap好像,想删除不让我删除,提示我超出文件长度啥的,嵌套好深,一层又一层…我win7系统…

感觉这个是node的优势,把依赖设计成树状而不是图状,能够很好的解决同一个模块的不同版本的依赖问题,这个浪费是非常值得的。

楼主,你确认你会用node_module? 一旦顶层有了这个module,下面就不再去下载了哦!

只能说 npm 和 node不是一起做的,npm的install -g 装到AppData\Roming\npm下面

node的require有全局路径 C:\user\Administrator.node_modules\ 但是npm 硬是自己搞一个

不爽npm可以自己搞一个出来吗,再搭个registry,就行了

好消息…lz 的愿望在未来的npm 3.0 将会实现…

http://tw.iojs.org/2015/02/24/npm-weekly-6/

ps: 看来npm现在有钱,有时间,有人开发复杂功能了…

看到标题就知道LZ肯定会被教育。。。进来一看,果然~~

楼主需要的是dedupe命令 npm help dedupe

不同嵌套深度的相同版本的模块会只被缓存一次?好像即使是两个相同版本的模块,还是会被当做完全独立的模块

这不是node的问题,你要是不嫌麻烦,把嵌套的node_modules里边的模块全部拷贝到根目录的node_modules里node运行也是没问题的。 楼主说的问题确实存在,windows用户应该经常碰到拷贝或者删除node_modules目录时系统报路径太长的错误,但那是npm的问题。

看了这么多其实我想问… 楼主是处女座的吧?

曾经因为目录路径太深,无法通过普通方式删除项目文件夹。

这么做的好处显而易见,a 依赖 b,c 依赖另一个版本的 b,两个版本的 b 差了一个大版本,不兼容。python 就很蛋疼,所有大环境只能用一套版本的包管理都很蛋疼。我是一个被 npm 宠坏的孩子,就是因为 node_modules。

npm dedupe 跑了半分多钟, 电脑都烫了

楼主可能不知道有个东西叫NODE_PATH环境变量。 此外,很多在全局安装过的包,在node_modules里是通过软链接的方式链接进去的。

这个时候跑过来挖坟是几个意思

npm3是模块就扁平化处理了,结果带来的麻烦是就是很难找对应的模块,依赖太多,一下子翻不过来.orz

挖你祖坟 哈哈

标题:Nodejs最恶劣的设计,就是node_modules了

内容: 确实,“node_modules”目录在Node.js项目中可能会变得非常庞大,并且包含许多重复的模块副本。这种设计在某些情况下会带来一些问题,尤其是在磁盘空间有限或构建时间较长的情况下。

为什么会有这么多副本?

当你的项目依赖于其他模块时,这些模块会被安装到node_modules目录下。有时候,你的项目依赖的某个模块A又依赖于模块B的不同版本。这时,Node.js为了确保兼容性,可能会在不同的子目录下安装不同版本的模块B。例如:

{
  "dependencies": {
    "moduleA": "^1.0.0",
    "moduleB": "^2.0.0"
  }
}

moduleA可能依赖于moduleB的另一个版本:

{
  "dependencies": {
    "moduleB": "^3.0.0"
  }
}

在这种情况下,Node.js会在node_modules/moduleA/node_modules/目录下安装moduleB3.0.0版本,在项目的根目录下的node_modules中也会安装moduleB2.0.0版本。这样会导致重复的模块副本,占用更多磁盘空间。

如何优化?

虽然这种情况有时不可避免,但可以通过以下方式来减少冗余模块:

  1. 统一依赖版本:尽可能使用相同的依赖版本。
  2. 清理未使用的模块:可以使用工具如npm prune来清理未使用的模块。
  3. 使用shrinkwrap文件:锁定特定版本的依赖,确保所有环境中的依赖版本一致。

示例:

# 清理未使用的依赖
npm prune

# 锁定依赖版本
npm shrinkwrap

通过上述方法,可以有效地管理和优化node_modules目录,减少磁盘空间的占用。

回到顶部