patch-package 補(bǔ)丁

前言

為什么要用到補(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í)行命令
  },
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容