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

发表于:2024-4-24 09:18

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:林三心不学挖掘机    来源:前端之神

#
前端
  幽灵依赖?
  前几天在公司的技术分享会上,我总是听到大佬们在提起一个名词——幽灵依赖,起初我没有太在意,以为这个不太重要,所以就没怎么去了解这个名词。
  直到我在做项目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而报错,所以它会顺利上线。。然后,等到了线上运行起来,直接报错!!!这是非常严重的的事故!
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号