背景
在开发过程中常常遇见node modules中的 A 包不完全满足使用场景或者有bug,常见的解决方式如下
1. 直接在 A 包找到代码块,进行源代码修改
优点:简单直接
缺点:只能本地自己使用、下次npm i后 A 包的代码又恢复原状
2. 把 A 包的源码拖出来自己维护,全局修改该包的引用地址,再针对该包做代码优化
优点:能应急使用
缺点:很暴力且事后维护成本较高
3. 把问题提给作者,等待发布
优点:不用操心了
缺点:做好石沉大海或修复周期很长的准备
patch-package
patch-package
相当于是在给A包打补丁及记录修改记录,就算重新npm i 根据补丁对A包重新进行修改,但对npm包入口是build后的文件就不可行
第一步 安装依赖
npm i patch-package
yarn add patch-package postinstall-postinstall
使用yarn的话需要这个postinstall-postinstall
包
为什么 yarn 要用 postinstall-postinstall 的官方解释
总结下就是确保在yarn remove时依旧能保持更正代码
第二步 修改 node_modules
拿lodash当A包举例 修改lodash的isEqual方法
function baseIsEqual(value, other, bitmask, customizer, stack) {
//此处三等改为两等
if (value == other) {
return true;
}
if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
return value !== value && other !== other;
}
return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
}
function isEqual(value, other) {
console.log("记录下进来了");
return baseIsEqual(value, other);
}
第三步 生成修改文件
npx patch-package lodash
这个时候你的项目根目录下会出现patches这个目录,里面会出现一个lodash的补丁文件,大致内容如下
index 4131e93..8020ee5 100644
--- a/node_modules/lodash/lodash.js
+++ b/node_modules/lodash/lodash.js
@@ -3307,7 +3307,8 @@
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
*/
function baseIsEqual(value, other, bitmask, customizer, stack) {
- if (value === other) {
+
+ if (value == other) {
return true;
}
if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
@@ -11597,6 +11598,7 @@
* // => false
*/
function isEqual(value, other) {
+ console.log("记录下进来了");
return baseIsEqual(value, other);
}
第四步修改 package.json
在package.json的script
中增加
"scripts": {
+ "postinstall": "patch-package"
}
ps:在 scripts
字段里可以自定义的脚本以及使用一些特殊脚本,这里的作用是每次npm i时 会去读取patches目录下的补丁文件,并将补丁打到对应的包里
此时可以重新装一下依赖,测试一下结果,即便重装依赖,我们对 node_modules
下代码的修改还是被 patch-package
还原并最终生效。再把patches目下的补丁文件上传到git,同事也可以同步修改的包,至此我们便完成一次临时打补丁的操作
特定的 scripts
对于以下脚本,npm
支持 package.json
文件的 scripts
默认命令字段:
prepublish
: 在打包并发布包之前运行,以及在没有任何参数的本地npm
安装之前运行。 (见下文)prepare
: 在打包和发布包之前运行,在没有任何参数的本地npm install
上运行,以及安装 git 依赖项时(见下文)。 这是在preublish
之后运行,但是在preublishOnly
之前运行。prepublishOnly
: 在包准备和打包之前运行,仅限于npm发布。 (见下文。)prepack
: 在打包tarball
之前运行(在npm pack
,npm publish
,以及安装 git 依赖项时)postpack
: 在生成tarball
之后运行并移动到其最终目标。publish
,postpublish
: 在包发布后运行。preinstall
: 在安装软件包之前运行。install
,postinstall
: 安装包后运行。preuninstall
,uninstall
: 在卸载软件包之前运行。postuninstall
: 在卸载软件包之后运行。preversion
: 在改变包版本之前运行。version
: 改变包版本后运行,但提交之前。postversion
: 改变包版本后运行,然后提交。pretest
,test
,posttest
: 由npm test
命令运行。prestop
,stop
,poststop
: 由npm stop
命令运行。prestart
,start
,poststart
: 由npm start
命令运行。prerestart
,restart
,postrestart
: 由npm restart
命令运行。 注意:如果没有提供重启脚本,npm restart
将运行stop
和start
脚本。preshrinkwrap
,shrinkwrap
,postshrinkwrap
: 由npm shrinkwrap
命令运行。
参考文档:npm docs.