直接修改 node_modules 下的代码不是被推荐的做法,应该仅在应急情况下考虑
在实际开发过程中当我们遇到node_modules
中的 A 包有 bug 时候,通常开发者有几个选择:
方法一:给 A 包提 issue 等待他人修复并发布:做好石沉大海或修复周期很长的准备。
方法二:给 A 包提 mr 自行修复并等待发布:很棒,不过你最好祈祷作者发版积极,并且新版本向下兼容。
方法三:把 A 包的源码拖出来自己维护:有点暴力且事后维护成本较高,不过应急时也能勉强接受。
等等,可如果出问题的包是幽灵依赖呢,比如项目的依赖链是: A -> B -> C,此时 C 包有 bug。那么上面三个方法的改动需要同时影响到 A、B、C 三个包,修复周期可能就更长了,可是你今晚就要上线啊,这可怎么办?
上线要紧,直接手动修改node_modules
下的代码给缺陷包打个临时补丁吧,可问题又来了,改动只能在本地生效,构建却在云端, 积极的同学开始写起了脚本,然后陷入一个个坑里...
上述场景下即可考虑使用patch-package这个包,假设我们现在的源码结构如下所示:
├── node_modules
│ └── lodash
│ └── toString.js
├── src
│ └── app.js // 依赖 lodash 的 toString 方法
└── package.json
node_modules/lodash/toString.js
varbaseToString=require(./_baseToString)functiontoString(value){returnvalue==null?:baseToString(value);}module.exports=toString;
src/app.js
consttoString=require(lodash/toString)console.log(toString(123));
假设现在需要修改node_modules/lodash/toString.js
文件,只需要遵循以下几步即可优雅完成修改:
第一步:安装依赖
yarn add patch-package postinstall-postinstall -D
第二步:修改node_modules/lodash/toString.js
文件
functiontoString(value){console.log(it works!!!);// 这里插入一行代码returnvalue==null?:baseToString(value);}module.exports=toString;
第三步:生成修改文件
npx patch-package lodash
这一步运行后会生成patches/lodash+4.17.21.patch
,目录结构变成下面这样:
├── node_modules
│ └── lodash
│ └── toString.js
├── patches
│ └── lodash+4.17.21.patch
├── src
│ └── app.js
└── package.json
其中 .patch 文件内容如下:
diff --git a/node_modules/lodash/toString.js b/node_modules/lodash/toString.jsindex daaf681..8308e76 100644--- a/node_modules/lodash/toString.js+++ b/node_modules/lodash/toString.js@@ -22,6 +22,7 @@ var baseToString = require(./_baseToString);* // => 1,2,3
*/
function toString(value) {+ console.log(it works!!!);return value == null ? : baseToString(value);
}
第四步:修改package.json
文件
"scripts":{+"postinstall":"patch-package"}
最后重装一下依赖,测试最终效果:
rm -rf node_modules
yarn
node ./src/app.js
// it works!!!
// 123
可以看到,即便重装依赖,我们对node_modules
下代码的修改还是被patch-package
还原并最终生效。
至此我们便完成一次临时打补丁的操作,不过这并非真正优雅的长久之计,长期看还是需要彻底修复第三方包缺陷并逐步移除项目中的.patch
文件。
参考资料: