修改 node_modules 里文件的正確姿勢


前言

我們在開發的時候經常會遇到這種情況:

  1. 所依賴的 npm 包有 bug,別人一時半會更新不了
  2. 不滿足自己的需求(比如一些 UI 框架),需要修改某些部分

那么這個時候我們就要去修改 node_modules 里面的源碼,直接修改會導致兩個問題:

第一,更新問題,重新安裝之后,修改的文件會被覆蓋

第二,同步問題,node_modules 里的文件一般是不提交到代碼庫的,那如何讓團隊其他成員也能同步更新呢?你總不能每次改完之后都手動發給其他人吧。

你可能首先想到的解決辦法有這樣兩個:

  1. 把別人代碼全部復制到自己的 src 目錄,修改完之后引入
  2. 把別人代碼下載到本地,修改完之后重新發布為一個包,然后再安裝自己發布的這個包

但這兩個解決辦法都有上述提到的更新問題,當這個依賴包有更新時,沒法自動同步更新。而且我們引入依賴包的時候,往往引入的是編譯之后的代碼,這樣會導致每次修改完代碼之后,還得自己手動編譯,很麻煩,那有沒有其他更好的解決辦法呢?答案是肯定的。我想到的有這樣幾個解決辦法,我們來逐一分析一下。

說明

以下所有解決方案都以 request 包為例進行演示。

npm link 相當於建立一個軟連接,將我們依賴的包鏈接到我們修改之后的包,這個在調試本地包的時候經常會用到,下面我們來實際操作一下。

  1. fork request 的倉庫到自己的倉庫,我這里命名為 request-study

  2. clone 到本地

  3. 進入到 request-study 目錄,執行 npm link
    image

  4. 進入到我們的工程目錄,執行 npm link request

    image

  5. 修改包文件里面的代碼,這里我們修改的目錄是 request-study/lib/auth.js
    image

這樣當包里面的文件更新的時候會自動同步到工程項目里面,解決了上述更新的問題。不足的一個地方是當依賴包有更新時,團隊其他成員也需要拉取最新的依賴包代碼。

webpack alias

webpack alias 的作用是配置別名,比如像這樣:

chainWebpack: config => {        
    config.resolve.alias        		
        .set('@', resolve('./src'))        		
        .set('request/a', resolve('./src/a'))
}

所以我們可以利用 webpack alias 將需要修改的文件代理到我們自己的項目文件中,操作步驟如下:

  1. 找到別人源碼里面的需要修改的文件,復制到 src 目錄
  2. 修改代碼,注意里面引用其他的文件路徑都需要改成絕對路徑
  3. 找到這個模塊被引入的路徑(我們需要攔截的路徑
  4. 配置 webpack alias

我們來實際操作一下。

我們修改的文件如下:

image

文件被引用的路徑為 ./lib/auth (我們要攔截的路徑)

image

將 auth.js 文件復制到 src/assets/auth.js,將 require 路徑中引入為當前request包的路徑修改為絕對路徑,並添加我們的代碼

image

配置 webpack alias (我這里用的是 vue-cli4, 配置文件是 vue.config.js),配置代碼為

const path = require('path');
module.exports = {
  chainWebpack: config => {
    config.resolve.alias
      .set('./lib/auth', path.resolve(__dirname, 'src/assets/auth.js'))
  }
};

啟動我們的項目,控制台打印出我們添加的代碼,表明我們的代碼添加成功。

image

當依賴包的代碼有更新時,我們也能同步更新,團隊其他成員同步修改的代碼時也不需要做其它額外的操作。不足的一個地方是當我們修改的依賴包是在配置文件中(比如 vue.config.js)引入時,這個不會生效。

yarn patch

這個需要用到 v2 版本的 yarn,具體步驟如下:

  1. 全局安裝 Yarn 的最新版本:npm install -g yarn ,這里說明一下,如果你之前安裝的是應用程序版本,需要先卸載之后再運行這個命令,不然安裝完成之后還是之前的 yarn 版本。

  2. 進入你的項目目錄,運行 yarn set version berry 命令。
    image

  3. 執行 yarn patch request 命令

    image

  4. 在如上圖所示文件路徑中修改代碼

  5. 在你的項目根目錄新建一個 patches 文件夾,執行 yarn patch-commit C:\Users\TWITTY~1\AppData\Local\Temp\xfs-f6241b39 > E:\vue-cli4\patches\request+2.88.2.patch,這樣你就能在 patches 文件下看到生成了一個 request+2.88.2.patch 文件,里面保存有你剛才修改代碼的 diff 內容。

  6. 修改package.json 文件如下:

    - "request": "^2.88.2" 
    + "request": "patch:request@^2.88.2#./patches/request+2.88.2.patch"
    
  7. 重新運行 yarn 和 啟動項目,你就能看到依賴包代碼修改之后的變化

    image

這種辦法解決了上述更新和團隊成員同步問題,缺點是操作起來比較繁瑣,還得依賴 v2 版本的 yarn。

yarn patch 可能出現的問題:

  1. 運行 yarn set version berry 時,如果出現類似以下這種錯誤

    image

    則可能需要用代理,命令行配置代理方法如下:

    windows:

    set http_proxy=http://127.0.0.1:1080
    set https_proxy=http://127.0.0.1:1080
    

    mac:

    export http_proxy=http://127.0.0.1:1080
    export https_proxy=http://127.0.0.1:1080
    
  2. 運行 yarn patch request 命令時,如果出現以下這種情況,則需要刪除 yarn.lock 文件,重新執行 yarn install

    image

    具體可以參考我的另一篇文章—記錄一次使用 yarn patch 遇到的問題

  3. 運行 yarn patch request 命令時,如果出現以下這種情況,說明有多個版本的包共存,你可以選擇你具體要修改的那個包版本,比如我想修改的是 request 的2.88.2 版本,就執行 yarn patch request@npm:2.88.2

    image

patch-package

操作步驟如下:

  1. 修改package.json 文件如下:

    "scripts": {
    + "postinstall": "patch-package"
    }
    
  2. 安裝 patch-package: npm i patch-package -S

  3. 在 node_modules 里面修改依賴包的代碼

  4. 每次修改代碼之后執行命令 npx patch-package request

最終會在項目根目錄生成一個 patches 文件夾,里面保存着修改過的文件記錄。

image

你可能已經看到了,這種解決辦法和 yarn patch 很像。是的,patch-package 可以看作是 yarn patch 的簡化版,它相當於封裝了 yarn patch 繁瑣的操作。

總結

我們總結一下四種方法:

npm link 團隊其他成員更新時需要同時更新修改依賴包;

webpack alias 不適用配置文件依賴的包;

yarn patch 需要將 yarn 升級到 v2 版本,操作步驟多;

patch-package 可以看做是 yarn patch 的一種替代方案,簡化了 yarn patch 的很多操作,是一個比較理想的解決方案。

最后

碼字不易,如果覺得對你有點幫助的話,還請動動你可愛的小指,幫忙點個贊;

如果你還有其他解決辦法或者問題,也歡迎留言交流。

參考資料:

https://juejin.cn/post/6844904163558555662

https://yarnpkg.com


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM