文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

在前端中,什么是幽灵依赖?

2024-11-29 23:33

关注

幽灵依赖?

前几天在公司的技术分享会上,我总是听到大佬们在提起一个名词——幽灵依赖,起初我没有太在意,以为这个不太重要,所以就没怎么去了解这个名词。

直到我在做项目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的规则的话,那么目录的结构应该是这样的

node_modules
├── npm-lsx 
|   └── node_modules
|       └── npm-test

但是如果依赖关系很长的话,那么会导致目录深度非常深,所以我们常用的npm、yarn解决了这个问题

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为幽灵依赖!!!

幽灵依赖的坏处?

某天 npm-lsx 不依赖 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而报错,所以它会顺利上线。。然后,等到了线上运行起来,直接报错!!!这是非常严重的的事故!

来源:前端之神内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯