结论:
- 1. npm uninstall会备份包本身依赖的node_modules,rm -f会删除整个目录
- 2. npm uninstall不会删除被依赖的包。即使显式要删除这个包,但它被依赖不会删除。rm -f会
- 3. npm uninstall有全局模式,还会删除软链,rm -r只删目录,可能漏掉软链
- 4. npm uninstall会删除package.json中的dependencies条目,rm -r不会
- 5. npm uninstall会安装那些在package.json中漏装的包,rm -r当然不可能有这个副作用
总之,npm uninstall和npm install是同一套代码,同一逻辑,都是【同步当前包环境】的操作。而rm -r是强制删除一个目录。
从名称上看,uninstall确实命名不佳,它非常复杂,和install一样复杂,是整个npm设计的核心,容易误解成删除。
没有文档,只能看代码,哎
分析:
比如,要删除 mkdirp
npm uninstall mkdir
会执行下列操作
第一步 加载本地实际存在的包列表
第二步 加载 package.json 得到理想包列表
通过分析package.json得到列表
loadAllDepsIntoIdealTree
在IdealTree中过滤掉要删除的包,这样就得到两个Tree,一个是 CurrentTree,一个是 IdealTree
第三步 同步CurrentTree和IdealTree
- 1. 如果CurrentTree中存在,IdealTree中不存在,忽略
- 2. 如果CurrentTree中不存在,IdealTree中存在,则安装
- 2. 如果CurrentTree中存在,IdealTree中不存在,则删除
第四步 执行删除操作的逻辑
- 1. 如果要删除的包被当前IdealTree中其它包依赖,则不删除
- 2. 如果要删除的包中有依赖的包,则备份它们,稍候恢复
mv ./node_modules/mkdirp/node_modules ./node_modules/.mkdirp.MODULES
rm -rf ./node_modules/mkdirp/
mkdir ./node_modules/mkdirp
mv ./node_modules/.mkdirp.MODULES ./node_modules/mkdirp/node_modules
使用 rimraf删除目录,rimraf是个包,它提供类似rm -rf的功能,递归的删除目录和文件,有重试逻辑等。
看似简单的 rm -rf为什么要单独实现呢?
nodejs fs模块早期确实没提供rm -r的功能,fs模块只提供了删除单个目录和单个文件的能力。
在 v12.10.0 后提供了递归删除目录的api,在 v14.14.0 提供了rm -rf的api。
来的太迟了,所以在开发npm的时候,就采用了rimraf这个包。
如果要删除的包中,没有node_modules,则不会执行备份的操作。