[TOC] >[success] # node_modules 层级 ~~~ 1.在 npm 的早期版本, npm 处理依赖的方式简单粗暴,以'递归的形式',在npm3版本 后采用了'扁平结构' ~~~ >[danger] ##### npm2.x 版本node_modules 层级 ~~~ 1.执行 'npm install' 后,'npm' 根据 'dependencies' 和 'devDependencies' 属性中指定的包 来确定第一层依赖,npm 2 会根据第一层依赖的子依赖,递归安装各个包到子依赖的 'node_modules' 中,直到子依赖不再依赖其他模块。执行完毕后,我们会看 到 './node_modules' 这层目录中包含有我们 'package.json' 文件中所有的依赖包,而这些 依赖包的子依赖包都安装在了自己的 'node_modules' 中 结构目录: ├── node_modules │   ├── A@1.0.0 │   │   └── node_modules │   │   │   └── D@1.0.0 │   ├── B@1.0.0 │   │   └── node_modules │   │   │   └── D@2.0.0 │   └── C@1.0.0 │   │   └── node_modules │   │   │   └── D@1.0.0 ~~~ * 结构层级图 ![](https://img.kancloud.cn/7c/49/7c49d39e574b71f073e2312e8169d32a_842x322.png) ~~~ 1.果你依赖的模块非常之多,你的 node_modules 将非常庞大,嵌套层级非常之深, 出现下图的效果,并且也会导致接下来的问题 1.1.在不同层级的依赖中,可能引用了同一个模块,导致大量冗余,举个例子当我的 A, B,C 三个包中有相同的依赖 D 时,执行 npm install 后,D 会被重复下载三次 1.2.在 Windows 系统中,文件路径最大长度为260个字符,嵌套层级过深可能导致不可 预知的问题。 ~~~ ![](https://img.kancloud.cn/8a/9c/8a9c81a778100b1f2f19126325628378_1280x859.png) >[danger] ##### npm3.x 版本 ~~~ 1.npm3.x 版本后采用了扁平化的解决方案,把依赖以及依赖的依赖平铺'node_modules' 文件夹下共享使用,npm 3 会遍历所有的节点,逐个将模块放在 'node_modules'的第一 层,当发现有重复模块时,则丢弃, 如果遇到某些依赖版本不兼容的问题,则继续采用 npm 2 的处理方式,前面的放在 'node_modules' 目录中,后面的放在依赖树中。 '过程说明': 下图 'A','B' 都依赖'D(v0.0.1)'那么在安装的时候将'A'的依赖包都平铺到'node_modules', 即将'D(v0.0.1)'平铺到了'node_modules' ,此时到了安装B包发现B包依赖在 'node_modules' 根已经重复这时候就跳过了,但是安装C的时候发现C也依赖'D'但是 依赖的版本不同,如果将C依赖的'D'放到'node_modules'根就因为重名问题覆盖掉 此时解决方案就像'npm2.x'的时候就将C依赖的'D(v0.0.2)'安装到了C的'node_modules' 下 ~~~ * 如图 ![](https://img.kancloud.cn/9f/49/9f4910f400ba6844c68e125c924ae165_562x302.png) * 是否解决npm2的 问题 ~~~ 1. 'A','B' 都依赖'D(v0.0.1)' ,'C' 依赖'D(v0.0.2)',如果先安装C 此时 在安装A,B时候由于 在安装'C'的时候'D(v0.0.2)' 被平级安装在'node_modules',因此'A','B''node_modules' 下都会有一个''D(v0.0.2)' npm 3 并未完全解决冗余的问题,甚至还会带来新的问题 ~~~ * 如图 ![](https://img.kancloud.cn/3b/19/3b193551344a0cbac5159f0b40b60463_563x272.png) >[info] ## 参考 [npm 依赖管理中被忽略的那些细节 ](https://www.infoq.cn/article/qj3z2ygrzdgicqauaffn) >[danger] ##### npm5.x 版本 ~~~ 1.从npm 5.x开始,安装组织node_modules和npm 3.x一样采用了扁平化的方式,最大的变化是增加了 package-lock.json 文件,npm 3.x有的问题他也有 2.package-lock.json 中已经缓存了每个包的具体版本和下载链接,不需要再去远程仓库 进行查询,然后直接进入文件完整性校验环节,减少了大量网络请求 ~~~