一、什么是 phantom dependencies(幽灵依赖)
一句话定义
phantom dependency(幽灵依赖)
指的是:
你的代码里import了一个包,但这个包并没有出现在你的package.json的dependencies里,却“刚好能跑”。
也叫:
- implicit dependency(隐式依赖)
- transitive dependency leakage(传递依赖泄漏)
二、一个非常典型的例子
package.json
{"dependencies":{"react-scripts":"^5.0.0"}}你的代码
importchalkfrom'chalk'问题是:
你没有在
dependencies里声明chalk但:
react-scripts内部依赖了chalk- npm / yarn 把
chalk装在了node_modules顶层
所以你的代码:
居然能正常运行
这时:
chalk就是一个phantom dependency
三、为什么会出现 phantom dependencies
Node.js 的模块解析机制
Node.js 是:
从当前目录 → 父目录 → 一直向上找 node_modules所以:
- 只要某个祖先目录有这个包
- 就能
require / import成功
npm / yarn 的 hoisting 行为
为了减少重复安装,包管理器会:
把**公共依赖提升(hoist)**到顶层
node_modules导致:
- 你能“看到”不属于你的依赖
四、phantom dependencies 有什么坏处(重点)
1. 构建 / CI / 生产环境不稳定
本地能跑 CI 挂了 别人机器挂了因为:
- 依赖树稍有变化
- hoist 结果就不同
2. 升级一个包,另一个项目突然炸
npmupdate react-scripts结果:
chalk被移除了 / 换版本- 你的代码直接
MODULE_NOT_FOUND
3. 依赖关系不清晰(工程灾难)
package.json看不出真实依赖npm prune可能误删- 审计 / 安全扫描不准确