238 - 《幽灵依赖》
发布于 2023年1月2日
1、什么是幽灵依赖?当一个项目使用了一个没有在其 package.json 中声明的包时,就会出现"幽灵依赖"。
比如你的 package.json 长这样,
{
"dependencies": {
"minimatch": "^3.0.4"
},
"devDependencies": {
"rimraf": "^2.6.2"
}
}
然后在代码中这么使用依赖,其中 brace-expansion 和 glob 就是幽灵依赖。
var minimatch = require('minimatch');
var expand = require('brace-expansion'); // ???
var glob = require('glob'); // ???
// 更多代码
那么,使用 devDependencies 里声明的 rimraf 算不上幽灵依赖?
const rimraf = require('rimraf');
答案是「看场景」。如果这是项目中的代码,不算;如果这是依赖库的代码,算。因为项目中安装依赖时会安装 devDependencies,而作为依赖库被项目安装时,不会安装依赖库的 devDependencies。
2、为啥使用幽灵依赖却能跑?这和 npm 的安装机制有关,npm 3.x 开始「改进」了安装算法,使其扁平化,扁平化就是把深层的依赖往上提。好处是消除重复依赖,代价则是引入幽灵依赖问题,因为往上提的依赖你在项目中引用时就能跑。(注:pnpm 默认配置彻底解决了幽灵依赖问题,当然他也没有依赖重复问题)
3、幽灵依赖最厉害的点在于,明明跑的好好的项目,过了一晚(也可能过了一周、一个月、一年)之后就挂了。原因在于,如果你没有明确声