如何“優雅”地修改 node_modules 下的程式碼?

語言: CN / TW / HK

直接修改 node_modules 下的程式碼不是被推薦的做法,應該僅在應急情況下考慮

在實際開發過程中當我們遇到 node_modules 中的 A 包有 bug 時候,通常開發者有幾個選擇:

方法一:給 A 包提 issue 等待他人修復併發布:做好石沉大海或修復週期很長的準備。

方法二:給 A 包提 mr 自行修復並等待發布:很棒,不過你最好祈禱作者發版積極,並且新版本向下相容。

方法三:把 A 包的原始碼拖出來自己維護:有點暴力且事後維護成本較高,不過應急時也能勉強接受。

等等,可如果出問題的包是“幽靈依賴”呢,比如專案的依賴鏈是: A -> B -> C,此時 C 包有 bug。那麼上面三個方法的改動需要同時影響到 A、B、C 三個包,修復週期可能就更長了,可是你今晚就要上線啊,這可怎麼辦?

1

上線要緊,直接手動修改 node_modules 下的程式碼給缺陷包打個臨時補丁吧,可問題又來了,改動只能在本地生效,構建卻在雲端, 積極的同學開始寫起了指令碼,然後陷入一個個坑裡...

上述場景下即可考慮使用 patch-package 這個包,假設我們現在的原始碼結構如下所示:

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

node_modules/lodash/toString.js

```javascript var baseToString = require('./_baseToString')

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

module.exports = toString; ```

src/app.js

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

假設現在需要修改 node_modules/lodash/toString.js 檔案,只需要遵循以下幾步即可“優雅”完成修改:

第一步:安裝依賴

shell yarn add patch-package postinstall-postinstall -D

第二步:修改 node_modules/lodash/toString.js 檔案

```javascript 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,目錄結構變成下面這樣:

javascript ├── node_modules │ └── lodash │ └── toString.js ├── patches │ └── lodash+4.17.21.patch ├── src │ └── app.js └── package.json

其中 .patch 檔案內容如下:

diff 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 檔案

json "scripts": { + "postinstall": "patch-package" }

最後重灌一下依賴,測試最終效果:

```shell rm -rf node_modules yarn node ./src/app.js

// it works!!! // 123 ```

可以看到,即便重灌依賴,我們對 node_modules 下程式碼的修改還是被 patch-package 還原並最終生效。

至此我們便完成一次臨時打補丁的操作,不過這並非真正優雅的長久之計,長期看還是需要徹底修復第三方包缺陷並逐步移除專案中的 .patch 檔案。

參考資料:

  • https://github.com/ds300/patch-package

關注微信公眾號“依賴注入”獲得更佳閱讀體驗。