主要区别在于依赖管理,其他的不重要,幽灵依赖是一种实现方案,即便是众矢之的。
幽灵依赖
简单讲,就是包的依赖不需要指定版本。比如你封装了一个工具包ABC
,该包的package.json
在开发期间依赖了React
/moment
/dayjs
等第三方库,但实际发布到仓库时可以从devDependencies
、dependencies
字段中移除掉这些依赖,但实际项目import "ABC"
使用时并不会报错,被包ABC
被丢掉的这些依赖叫幽灵依赖。
npm
npm
支持幽灵依赖,只要你的项目package.json
中有声明并安装这些依赖包即可,开发工具包不需要指定任何依赖。node
的包寻址方式从引用文件所在目录开始,往上不断找node_modules
文件夹,由于npm
使用扁平化的方式管理包,所以一定能寻址到node_modules
文件夹。
pnpm
pnpm
幽灵依赖支持方式比较绕。pnpm
一般用于多项目整合(monorepo)
,用例代码会单独拆成一个子项目,使用pnpm
开发工具包项目必须指定包的版本,否则用例项目引用工具包项目会出现Can't resolve XXX
报错。原因在于pnpm
使用软连接重定向了node
的包寻址,直接重定向到工具包项目的源代码目录,如果你的工具包项目node_modules
中使用幽灵依赖方案,就会直接抛异常,因为各个子项目的目录结构是平行的,往上寻址就会到达根目录。
解决
使用pnpm
开发,如果工具包子项目必须指定依赖版本,但用例项目又指定依赖版本,就会造成依赖的实现差异,这是填了旧坑结果又引出新坑?实际上pnpm
把所有包都放到了根项目node_modules/.pnpm
目录中,只要你在根项目(项目最外层文件夹)install
幽灵依赖,就会命中依赖。如果工具包被发布到仓库,从线上install
,那么会被安装到根项目node_modules/.pnpm
目录中,幽灵依赖也会命中。