ChatGPT 教我如何修改 node_modules 里的代碼
node_modules 里的包都是外部依賴,一般來說不應(yīng)該直接修改 node_modules 里的文件。但是凡事總有例外,總會碰到需要修改的場景,這里列舉兩個辦法。這兩個辦法都是 ChatGPT 教我的,親測有效,分享給大家。
發(fā)新包我用 vuejs/vitepress 寫文檔時,發(fā)現(xiàn) markdown 文件可以包含,但不支持嵌套包含。所以聯(lián)合 ChatGPT,修復(fù)了這個問題。整個過程大致如下:
克隆
因為沒有官方倉庫的修改權(quán)限,所以首先需要將官方的 vuejs/vitepress 克隆至自己的倉庫,接著就可以在自己的倉庫中修改代碼了。詳細過程見:《【已被采納】基本功不好,如何做開源貢獻?使用 ChatGPT 寫代碼實錄。 ? 》
貢獻
不妨將自己的修改貢獻給原倉庫,這只需要發(fā)一個合并請求,詳見上文。
發(fā)自己的包
然后,就可以等待維護者的審核了,如果通過審核,還需要等待官方發(fā)新版,才能在自己的依賴中更新版本從而使用到自己的修改。如果等不及,但想提前使用自己修改過的版本,就可以發(fā)自己的包。
在上例中,我修改的版本雖然已經(jīng)得到采納,但是目前新的版本還沒有發(fā)出來,為了提前使用嵌套包含功能,我從主分支拉出一個新的分析 jeff,并將 package.json 做了必要修改后,發(fā)了一個新包:@jeff-tian/vitepress。這樣,只需要引用該包,就能立即使用到新的功能了。
npm i @jeff-tian/vitepress --save
為了發(fā)新包,需要做的修改詳見:https://github.com/vuejs/vitepress/commit/b35de817436d57dee84cc369bb28b7ae1bef0493
{
- "name": "vitepress",
- "version": "1.0.0-beta.3",
- "description": "Vite & Vue powered static site generator",
+ "name": "@jeff-tian/vitepress",
+ "publishConfig": {
+ "access": "public"
+ },
+ "version": "1.0.0",
+ "description": "Vite & Vue powered static site generator, support nested inclusion",
"type": "module",
"packageManager": "[email protected]",
"main": "dist/node/index.js",
post install
在上面的場景下,發(fā)新包的方式非常適合。然而,有些情況下,則不一定適合。比如,要修改的文件不在項目的直接依賴包里,而是嵌套 n 層,非常底層。如果用發(fā)新包的方式,那么整個依賴樹中都得依次更新 package.json,并將每個包都發(fā)一遍。這樣做的話工作量大到幾乎不可能完成。
這時候,可以利用 post install,做文件內(nèi)容的查找替換,非常好用!
舉個例子
還是項目中用到了 vuejs/vitepress,發(fā)現(xiàn)在 markdown 文件中引用的圖片,如果文件名中有了空格,那么整個文檔站點編譯就會失敗,比如:
Could not resolve "./book/resources/test%20(1).svg" from "docs/index.md"
原因是 vitepress 依賴了一系列的包,最終最底層的 @vue/core 將文件名使用了 parseUrl 函數(shù)處理過,導(dǎo)致空格被編碼成了 %20,從而在 nodejs 里的 import 過程中,出現(xiàn)找不到文件的錯誤。
盡管說在文件名里使用空格是非常不推薦的,但由于操作系統(tǒng)支持這樣的文件名,并且很多過程會自動產(chǎn)生包含空格的文件名,所以我個人認為非常有必要在 vue 生態(tài)中支持這樣的文件名。
這個問題很多人反映過:
-
https://github.com/vuejs/vitepress/issues/2596
-
https://github.com/vuejs/vitepress/issues/573
-
https://github.com/vitejs/vite/issues/7300
-
https://github.com/vuejs/vuepress/issues/2152
但是 2 年多了官方也沒有計劃做修復(fù)。
修復(fù)
我決定修復(fù)一下,并嘗試貢獻回官方倉庫:https://github.com/vuejs/core/pull/8752。但是估計不會很快得到響應(yīng),于是需要一個臨時解決方案。
如果通過發(fā)一個新包,那么我還需要順著依賴樹改所有的相關(guān)依賴,放棄。
post install 來幫忙
于是我就問 ChatGPT 該怎么辦?


我試了一下,居然好用!這里將詳細的代碼再用文字貼一遍,如果你也需要在 vue 生態(tài)的 markdown 文件中,使用帶空格的靜態(tài)文件資源,可以閉眼粘貼使用。
創(chuàng)建 postinstall.js 文件
const fs = require('fs');
const filePath = 'node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js';
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
console.error(err);
return;
}
const modifiedData = data.replace(
/context.imports\.push\(\{\s*exp,\s*path:\s*path2\s*}\);/g,
"context.imports.push({ exp, path: path2 && path2[0] === '/' ? decodeURIComponent(path2) : path2 });"
);
fs.writeFile(filePath, modifiedData, 'utf8', (err) => {
if (err) {
console.error(err);
return;
}
console.log('File modified successfully!');
});
});
在 package.json 的 scripts 節(jié)增加
+ "postinstall": "node postinstall.js"
后面再執(zhí)行一次 npm install 后,空格帶來的麻煩就消失了!
總結(jié)ChatGPT 教會了我兩個修改 node_modules 目錄下的文件的方法,如果是第一層依賴的代碼,可以直接修改后發(fā)新包,省得做文件內(nèi)容替換。如果是第 n 層的依賴,建議使用 postinstall 腳本進行文件內(nèi)容替換。
