ChatGPT 教我如何修改 node_modules 里的代码

哈德韦

共 4509字,需浏览 10分钟

 · 2023-07-13

node_modules 里的包都是外部依赖,一般来说不应该直接修改 node_modules 里的文件。但是凡事总有例外,总会碰到需要修改的场景,这里列举两个办法。这两个办法都是 ChatGPT 教我的,亲测有效,分享给大家。

发新包

我用 vuejs/vitepress 写文档时,发现 markdown 文件可以包含,但不支持嵌套包含。所以联合 ChatGPT,修复了这个问题。整个过程大致如下:

克隆

因为没有官方仓库的修改权限,所以首先需要将官方的 vuejs/vitepress 克隆至自己的仓库,接着就可以在自己的仓库中修改代码了。详细过程见:《【已被采纳】基本功不好,如何做开源贡献?使用 ChatGPT 写代码实录。  

贡献

不妨将自己的修改贡献给原仓库,这只需要发一个合并请求,详见上文。

发自己的包

然后,就可以等待维护者的审核了,如果通过审核,还需要等待官方发新版,才能在自己的依赖中更新版本从而使用到自己的修改。如果等不及,但想提前使用自己修改过的版本,就可以发自己的包。

在上例中,我修改的版本虽然已经得到采纳,但是目前新的版本还没有发出来,为了提前使用嵌套包含功能,我从主分支拉出一个新的分析 jeff,并将 package.json 做了必要修改后,发了一个新包:@jeff-tian/vitepress。这样,只需要引用该包,就能立即使用到新的功能了。

      
        npm i @jeff-tian/vitepress --save
      
    

为了发新包,需要做的修改详见: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": "pnpm@8.6.3",
      
      
          "main": "dist/node/index.js",
      
    
post install

在上面的场景下,发新包的方式非常适合。然而,有些情况下,则不一定适合。比如,要修改的文件不在项目的直接依赖包里,而是嵌套 n 层,非常底层。如果用发新包的方式,那么整个依赖树中都得依次更新 package.json,并将每个包都发一遍。这样做的话工作量大到几乎不可能完成。

这时候,可以利用 post install,做文件内容的查找替换,非常好用!

举个例子

还是项目中用到了 vuejs/vitepress,发现在 markdown 文件中引用的图片,如果文件名中有了空格,那么整个文档站点编译就会失败,比如:

      
        Could not resolve "./book/resources/test%20(1).svg" from "docs/index.md"
      
    


原因是 vitepress 依赖了一系列的包,最终最底层的 @vue/core 将文件名使用了 parseUrl 函数处理过,导致空格被编码成了 %20,从而在 nodejs 里的 import 过程中,出现找不到文件的错误。

尽管说在文件名里使用空格是非常不推荐的,但由于操作系统支持这样的文件名,并且很多过程会自动产生包含空格的文件名,所以我个人认为非常有必要在 vue 生态中支持这样的文件名。

这个问题很多人反映过:

  • 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 年多了官方也没有计划做修复。

修复

我决定修复一下,并尝试贡献回官方仓库:https://github.com/vuejs/core/pull/8752。但是估计不会很快得到响应,于是需要一个临时解决方案。

如果通过发一个新包,那么我还需要顺着依赖树改所有的相关依赖,放弃。

post install 来帮忙

于是我就问 ChatGPT 该怎么办?

334cdc0cf1547a20a26c7b18dbbe7391.webpce58f64a0278b491c6ecceef0c4038a9.webp


我试了一下,居然好用!这里将详细的代码再用文字贴一遍,如果你也需要在 vue 生态的 markdown 文件中,使用带空格的静态文件资源,可以闭眼粘贴使用。

创建 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 节增加

      
        +     "postinstall": "node postinstall.js"
      
    


后面再执行一次 npm install 后,空格带来的麻烦就消失了!

总结

ChatGPT 教会了我两个修改 node_modules 目录下的文件的方法,如果是第一层依赖的代码,可以直接修改后发新包,省得做文件内容替换。如果是第 n 层的依赖,建议使用 postinstall 脚本进行文件内容替换。


浏览 51
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报