惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
罗磊的独立博客
量子位
Microsoft Azure Blog
Microsoft Azure Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
M
MIT News - Artificial intelligence
月光博客
月光博客
IT之家
IT之家
D
DataBreaches.Net
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Last Week in AI
Last Week in AI
D
Docker
The GitHub Blog
The GitHub Blog
B
Blog
V
Visual Studio Blog
博客园 - Franky
N
Netflix TechBlog - Medium
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
博客园 - 聂微东
U
Unit 42

灯火不休时

给国行iPhone用户看的WWDC26 重复造轮子之简易RPC框架 Spring AOP 动态代理机制:从静态代理到 JDK 与 CGLIB 的实现 从零手写一个 Spring Boot Starter:深入理解自动装配原理 LangChain4j工具调用中断引发JSON格式报错的问题调查 基于CNN深度学习网络的交通标志识别 策略模式优化多重判断 CSS多行溢出,兼容性比较好的做法 Hadoop集群搭建(1主2从) 利用PyCharm简化搭建深度学习环境(新手排坑) Win10简洁之道 栈与队列的应用 顺序表的增删改查
NPM包管理工具的幻影依赖问题
灯火不休时 · 2024-08-27 · via 灯火不休时

随着前端工程化的不断完善,各种包管理工具和构建工具也越来越多。在Node生态里,绕不开NPM,Yarn,PNPM这些包管理工具,但是项目中一般都是用PNPM包管理工具而不用NPM,有一部分原因就是因为NPM包管理工具容易产生幻影依赖的问题。

随着前端工程化的不断完善,各种包管理工具和构建工具也越来越多。在Node生态里,绕不开NPM,Yarn,PNPM这些包管理工具,但是项目中一般都是用PNPM包管理工具而不用NPM,有一部分原因就是因为NPM包管理工具容易产生幻影依赖的问题。

幻影依赖

假设我们使用 npm install 命令给我们的项目安装 element-plus 依赖,安装后在 node_modules 文件夹下查看依赖文件,会发现有很多文件夹,有很多依赖都被下载下来了,这是因为 element-plus 等项目的直接依赖有很多间接依赖,也就是我们的项目依赖A,而A又依赖B,B又依赖C, A→B→C,所有的这些依赖都被安装到了node_modules 里。

而这里的依赖B,或者依赖C虽然我们没有在packages.json里,但是却可以在代码里直接引入使用,直接 import xxx 就行。

也就是说,在我们代码里面可以直接使用一个在依赖申明文件 packages.json 中并不存在的依赖,这就是幻影依赖。

幻影依赖产生的问题

幻影依赖至少会产生2个问题:

假设目前代码是这种情况:申明了A依赖,A→B,因为A依赖了B,所以在代码里直接使用了B。

  1. 依赖的版本问题: 这时如果A刚好有新版本升级了,A升级会自动升级A所依赖的B,这时代码里直接使用的B依赖就很有可能报错。如果在生产环境里遇到这个问题,一般是很难排查的。
  2. 依赖丢失问题: 这时,如果我们的A依赖是开发环境dev的依赖,放到生产环境的话是不存在A依赖的,此时代码在本地开发环境可以正常运行,而在生产环境,就会报错了。

NPM包管理工具也有在解决这个幻影依赖的问题,只是没有很好的解决。

问题产生的根源:依赖图和文件树是不同的。一个是图结构,一个是树结构。

树是一种“层次结构”,图是一种“网络”关系。

假设项目中的真实依赖是上图中左边的依赖图,项目直接依赖了A,A间接依赖了B、C、D

NPM之前的解决方案是上图中右边的文件树,A依赖了B,B和C共同依赖了D,所以B依赖的文件夹里有一份D的源码,C依赖的文件夹里也有一份D的源码,这么做就造成了磁盘空间的浪费,导致依赖的体积进一步变大。

NPM后来借鉴了Yarn包管理工具的做法,不管间接依赖了多少包,统一都放到根目录 node_modules下,如下图:

这么做也还是无法避免幻影依赖的问题,只是解决了一部分磁盘占用空间大的问题。

PNPM包管理工具的解决方案

在PNPM中,所有的依赖包括间接依赖存储在类似一个容器的 store 中,就是 node_modules 文件夹中的 .pnpm 文件夹里,与 yarn 的存储类似,同时又使用类似快捷方式的做法(硬链接和软连接都有使用)在 node_modules 中构造了一个文件结构,如上图中虚线部分图示。而这个快捷方式因为只是链接到了store中的正式存储内容,所以并不占空间,又能很好的保留依赖的关系。并且在代码中引用只能引用到A,因为 B、C、D 都不在node_modules里,而是 .pnpm 里。

所以在实际开发中,更推荐用PNPM做包管理工具,不仅下载快,占用磁盘空间小,还能避免幻影依赖的问题。