前言
為什么要用到補(bǔ)丁呢?
開發(fā)中,可能會經(jīng)常遇到一種情況,使用npm安裝了一個(gè)第三方的庫,但是庫里面的某一段代碼有問題,或者是符合實(shí)際需求,需要進(jìn)行修改;但是修改完后,只能我自己用,其他同事開發(fā)的時(shí)候,還需要再去修改一遍,非常的麻煩,還容易出錯(cuò)。
而補(bǔ)丁神器patch-package應(yīng)用而生,它能幫助我們在正常安裝某個(gè) npm 依賴的情況下,通過在項(xiàng)目里增加一個(gè)補(bǔ)丁文件,就可以將對這個(gè) npm包的修改持久保存到項(xiàng)目中。這樣就能實(shí)現(xiàn)針對開源庫的 bug 修復(fù)直接應(yīng)用到項(xiàng)目中。
一、npm 安裝補(bǔ)丁
- 安裝
patch-package
npm install patch-package
- 修改
node_modules里某個(gè)包的源代碼
我這里以axios為例子
function ownKeys(e, r) {
// 增加一個(gè)輸出
console.log('======', e, r)
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r && (o = o.filter(function (r) {
return Object.getOwnPropertyDescriptor(e, r).enumerable;
})), t.push.apply(t, o);
}
return t;
}
- 生成補(bǔ)丁
npx patch-package axios
其中axios是我們需要創(chuàng)建補(bǔ)丁的庫。
補(bǔ)丁創(chuàng)建成功后,會在項(xiàng)目的根目錄下生成一個(gè)補(bǔ)丁文件夾patches,文件夾下有我們剛生成的補(bǔ)丁文件axios+1.6.8.patch

- 添加自動執(zhí)行命令
package.json
"scripts": {
....
"postinstall": "patch-package" // 自動執(zhí)行命令
},
- 測試:刪除
node_modules文件夾,重新執(zhí)行npm install,發(fā)現(xiàn):
效果
二、pnpm安裝補(bǔ)丁
如果使用pnpm管理三方庫,是不能安裝補(bǔ)丁的,執(zhí)行 npx patch-package heatmap.js時(shí)會報(bào)錯(cuò):
**ERROR** No package-lock.json, npm-shrinkwrap.json, or yarn.lock file.
You must use either npm@>=5, yarn, or npm-shrinkwrap to manage this project's
dependencies.
但是可以使用其他辦法:
1、使用已經(jīng)生成的補(bǔ)丁
使用其他的包管理器(例如
npm)生成補(bǔ)丁-
在根目錄下創(chuàng)建
patches文件夾,并且將補(bǔ)丁復(fù)制到該文件夾下
效果 添加自動執(zhí)行命令
package.json
2、腳本
原理:將修改后的源碼文件復(fù)制出來,放到項(xiàng)目里,在每次執(zhí)行pnpm install安裝依賴之后,使用腳本將修改后的文件復(fù)制到源碼目錄,覆蓋掉源代碼,實(shí)現(xiàn)修改代碼的目的。
- 將修改后的三方庫源碼文件復(fù)制到
patches文件夾下
源碼文件 - 在項(xiàng)目中創(chuàng)建一個(gè)腳本
postinstall.js,在腳本中實(shí)現(xiàn)代碼覆蓋
import fs from 'node:fs';
copyFileSync(
'./patches/heatmap.js/heatmap.js',
'./node_modules/heatmap.js/build/heatmap.js',
);
function copyFileSync(source, target) {
let targetFile = target;
// If target is a directory, a new file with the same name will be created
if (fs.existsSync(target) && fs.lstatSync(target).isDirectory()) {
targetFile = path.join(target, path.basename(source));
}
fs.writeFileSync(targetFile, fs.readFileSync(source));
}
- 添加自動執(zhí)行腳本命令
package.json
"scripts": {
......
"postinstall": "node scripts/postinstall.js" // 自動執(zhí)行命令
},


