注册

如何“优雅”地修改 node_modules 下的代码?

在实际开发过程中当我们遇到 node_modules 中的 A 包有 bug 时候,通常开发者有几个选择:


方法一:给 A 包提 issue 等待他人修复并发布:做好石沉大海或修复周期很长的准备。


方法二:给 A 包提 mr 自行修复并等待发布:很棒,不过你最好祈祷作者发版积极,并且新版本向下兼容。


方法三:把 A 包的源码拖出来自己维护:有点暴力且事后维护成本较高,不过应急时也能勉强接受。


等等,可如果出问题的包是“幽灵依赖”呢,比如项目的依赖链是: A -> B -> C,此时 C 包有 bug。那么上面三个方法的改动需要同时影响到 A、B、C 三个包,修复周期可能就更长了,可是你今晚就要上线啊,这可怎么办?


1


上线要紧,直接手动修改 node_modules 下的代码给缺陷包打个临时补丁吧,可问题又来了,改动只能在本地生效,构建却在云端, 积极的同学开始写起了脚本,然后陷入一个个坑里...


上述场景下即可考虑使用 patch-package 这个包,假设我们现在的源码结构如下所示:


├── node_modules  
│ └── lodash
│ └── toString.js
├── src
│ └── app.js // 依赖 lodash 的 toString 方法
└── package.json

node_modules/lodash/toString.js


var baseToString = require('./_baseToString')

function toString(value) {
return value == null ? '' : baseToString(value);
}

module.exports = toString;

src/app.js


const toString = require('lodash/toString')
console.log(toString(123));

假设现在需要修改 node_modules/lodash/toString.js 文件,只需要遵循以下几步即可“优雅”完成修改:


第一步:安装依赖


yarn add patch-package postinstall-postinstall -D

第二步:修改 node_modules/lodash/toString.js 文件


function toString(value) {
console.log('it works!!!'); // 这里插入一行代码
return value == 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.js
index 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 文件。


作者:王力国
链接:https://juejin.cn/post/7022252841116893215

0 个评论

要回复文章请先登录注册