大家好, 用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心。
前几天在公司的技术分享会上,我总是听到大佬们在提起一个名词——幽灵依赖,起初我没有太在意,以为这个不太重要,所以就没怎么去了解这个名词。
直到我在做项目pnpm迁移
的时候,我突然很想知道它跟幽灵依赖到底有什么关系呢?
其实在了解什么关系之前,我应该去了解一下什么是幽灵依赖,我们接着聊!!!
比如我现在,我在开发一个项目A,项目A中我装了npm-lsx
这个包,而这个npm-lsx
的包依赖了npm-test
,咱们来看看这两处packages.json
依赖关系是:A <- npm-lsx <- npm-test
// A/packages.json
{
"name": "A",
"dependencies": {
"npm-lsx": "^1.0.0"
}
}
// A/node_modules/npm-lsx/packages.json
{
"name": "npm-lsx",
"dependencies": {
"npm-test": "^1.0.0"
}
}
如果按照node_modules
的规则的话,那么目录的结构应该是这样的
node_modules
├── npm-lsx
| └── node_modules
| └── npm-test
但是如果依赖关系很长的话,那么会导致目录深度非常深,所以我们常用的npm、yarn
解决了这个问题
它们是怎么解决这个问题的呢?npm、yarn
为了解决依赖关系过长时,导致的目录结构过深,采用了扁平化
,也就是所有依赖都被拍平到node_modules
目录下。这样的好处就是,不再有层级过深的问题。
现在目录结构变成这样了
// A/node_modules
node_modules
├── npm-lsx
├── npm-test
接着上面的示例,继续聊,请看下面的代码
const lsx = require('npm-lsx')
const test = require('npm-test')
lsx()
test()
你们觉得这段代码有问题吗?其实运行起来是没问题的。但是问题来了,我们项目中居然能直接引用npm-test
这个包!!!
我们都知道依赖关系是:
A <- npm-lsx <- npm-test
按理说,A
是不能直接引用npm-test
的,因为没有直接依赖关系啊!!!但是因为前面说了,npm、yarn
会将依赖拍平在A的node_modules
中,这导致了A
可以直接require('npm-test')
我们称这个npm-test
为幽灵依赖!!!
已知你现在代码是这样
const lsx = require('npm-lsx')
const test = require('npm-test')
lsx()
test()
某天npm-lsx
升级了!它不再依赖npm-test
了!那么此时A
的node-modules
中变了!
// 以前
node_modules
├── npm-lsx
├── npm-test
// 现在
node_modules
├── npm-lsx
那么你的代码会报错!
const lsx = require('npm-lsx')
const test = require('npm-test') // 没有
lsx()
test() // 报错!!!
其实这个情况还好,因为这种情况在打包上线过程中就会报错依赖找不到了,所以不太会造成线上的报错崩溃
我现在有两个项目A和B
A中的node_modules
目录为,现阶段npm-test
的版本为1.0.0
// A/node_modules
node_modules
├── npm-lsx
├── npm-test 版本号:1.0.0
A中某个文件的代码为
const test = require('npm-test')
test()
B中某个文件的代码为
const test = require('npm-test')
test()
当有一天npm-lsx
所依赖的npm-test
升级了!版本升级为了2.0.0
// A/node_modules
node_modules
├── npm-lsx
├── npm-test 版本号:2.0.0
此时test
的用法也变了~而因为A项目已经回归过了,所以他知道,也改了对应的代码
const test = require('npm-test')
test.run() // 修改代码
而B项目就没那么好运了,它并没有进行回归,所以并没有去改代码!!!!
const test = require('npm-test') // 有
test() // 直接报错
这就惨了,B项目在打包阶段并不会因为依赖不到npm-test
而报错,所以它会顺利上线。。然后,等到了线上运行起来,直接报错!!!这是非常严重的的事故!
下一篇文章我会讲讲,pnpm
是怎么解决幽灵依赖问题的!敬请期待~~~
大家如果想了解dependencies和devDependencies的区别,可以读这篇文章
[dependencies和devDependencies有区分意义吗?]
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8