3.1 嵌套结构(以前版本)
在 npm 的早期版本, npm 处理依赖的方式简单粗暴,以递归的形式,严格按照 package.json 结构以及子依赖包的 package.json 结构将依赖安装到他们各自的 node_modules 中。直到有子依赖包不再依赖其他模块
例如:我的模块my-app现在依赖了两个模块:buffer,ignore:
{"name": "my-app",
"dependencies": {
"buffer": "^5.4.3",
"ignore": "^5.1.4",}
}
其中ignore是不依赖其他任何模块,而buffer又依赖了下面两个模块:base64-js , ieee754:
{"name": "buffer",
"dependencies": {
"base64-js": "^1.0.2",
"ieee754": "^1.1.4"}
}
那么,执行npm install 后,得到的node_modules中模块目录结构就如下图
但是如果依赖模块太多,会使嵌套层级非常深
3.2扁平结构
- 安装模块时,不管其是直接依赖还是子依赖的依赖,优先将其安装在
node_modules根目录。
还是上面的依赖结构,我们在执行 npm install 后将得到下面的目录结构
如果我们在模块中又依赖了base64-js@1.0.1版本
{"name": "my-app",
"dependencies": {
"buffer": "^5.4.3",
"ignore": "^5.1.4",
"base64-js": "1.0.1",
}
}
当安装到相同模块时,判断已安装的模块版本是否符合新模块的版本范围,如果符合则跳过,不符合则在当前模块的 node_modules 下安装该模块
对应的,如果我们在项目代码中引用了一个模块,模块查找流程如下:
- 在当前模块路径下搜索
- 在当前模块
node_modules路径下搜素 - 在上级模块的
node_modules路径下搜索 - ...
- 直到搜索到全局路径中的
node_modules
假设我们又依赖了一个包 buffer2@^5.4.3,而它依赖了包 base64-js@1.0.3,则此时的安装结构是下面这样的:
所以 npm 3.x 版本并未完全解决老版本的模块冗余问题,甚至还会带来新的问题。
试想一下,你的APP假设没有依赖 base64-js@1.0.1 版本,而你同时依赖了依赖不同 base64-js 版本的 buffer 和 buffer2。由于在执行 npm install 的时候,按照 package.json 里依赖的顺序依次解析,则 buffer 和 buffer2 在 package.json 的放置顺序则决定了 node_modules 的依赖结构:
先依赖buffer2:
先依赖buffer:
这样的依赖结构不确定性会带来很多问题