🔒️ 如何修改第三方npm包?

阿轩的BUG
文章191
评论56
标签101
站点日志
作者总数:1位
置顶文章:0篇
标签总数:101条
文章总数:196篇
评论总数:56条
微语总数:201条
运行天数:2320天
最近更新:2026-07-28
文章标签
最新评论
Sherlock
2025-08-21
不是应该打包成apk文件吗,怎么突然就运行编译了,下一步呢
老金er
2025-05-25
人生设计非常必要,在信息化发达的今天,周围大部分人依然只能过着人生工程模式生活,长时间生活洗礼后,尽管“人生工程”已经不再适合很多人,他们也无法做出任何改变,人生设计给我们提供了新的思路,值得尝试
赏帮赚
2025-05-25
职场太多的尔虞我诈
三笑
2024-08-16
emlog6.0.1可以升级支持吗?
pony
2024-07-08
这篇文章提供了一种新的人生规划方法——"人生设计",它借鉴了产品设计的理念,鼓励人们以创造性和探索性的方式思考和规划自己的生活。以下是对这篇文章的几个评价维度: 创新性:将产品设计的理念应用于人生规划是一个新颖的视角,为人们提供了一种跳出传统生活轨迹,探索个性化生活路径的方法。 实用性:文章不仅提出了理念,还详细介绍了具体的实施步骤,包括自我评估、制定计划、原型设计和实践选择等,具有很强的操作性。 启发性:通过强调好奇心、不断尝试、重新定义问题等心态,文章鼓励人们打破常规,勇于探索未知,这对于激发个人潜能和创造力具有积极作用。 适应性:"人生设计"理念适用于不同人生阶段和不同背景的人,无论是希望从头开始的人,还是已经取得一定成就但希望探索新方向的人,都可以从中获得启发。 情感共鸣:文章对许多人对传统生活轨迹的不满和对改变的渴望进行了深刻的洞察,能够引起读者的共鸣。 可持续性:人生设计强调的是一个持续迭代和试错的过程,这与现实生活的发展规律相吻合,有助于人们在不断变化的环境中做出适应性调整。 教育意义:作为一种人生规划方法,"人生设计"可以作为教育的一部分,帮助年轻人更早地学会自我探索和规划,为未来的生活和职业发展打下基础。 局限性:尽管"人生设计"提供了一种新的思考框架,但它可能需要个人具备一定的自我认知和反思能力,对于一些缺乏自我探索经验的人来说,可能需要额外的指导和支持。 总体来说,这篇文章提供了一种有价值的人生规划方法,对于那些渴望改变、寻求个性化生活的人来说,是一种有益的参考和指导。
首页实用干货 🌋

有这样一种场景:如果你在开发过程中,发现某个npm包有Bug,应该怎么办?

第一选择当然是向原作者提issue,或者Fork该仓库代码,修改以后,提交合并请求。

但这种情况有个严重的问题,就是耗时,如果遇到严格的作者,或者不活跃的作者,时间线可能会拉得很长。你的项目未必能等这么长时间。

还有一种可能是,你修改的代码并不具备普适性,只有你的业务场景能用到,合并被拒的概率会大大增加。

总而言之,如果能修改npm包的源包,再好不过,如果不行,则需要有个临时方案,或者替代方案。

这时,又有下面两种情况:

  1. 代码量少,可以直接修改npm包代码的,考虑补丁方案。
  2. 代码量多,或者npm包代码是压缩混淆过的,不具备修改条件。修改源码后,再修改包名,重新发布,在应用代码中更换引用。为叙文方便,我将这种方案命名为换日方案(偷天换日,李代桃僵)。

下面,详细介绍下这两种不同方案。

补丁方案

patch-packagepatch-package

patch-package是一个用于修复第三方依赖包的工具,使用方式非常简单。

它支持npm和yarn v1,如果是yarn v2+或者pnpm,则使用自带的patch方案(下文会介绍pnpm方案)。

安装:

npm i patch-package
yarn add patch-package postinstall-postinstall

如果只是前端使用,可以添加—dev或-D参数。如果是后端使用,为保障生产模式(会去除devDendencies依赖)也能正常使用,就不要加了。

node_modules 中找到你要修改的 npm 包,修改内容后,就可以运行 patch-package 创建 patch 文件了。

npx patch-package package-name   # 使用npm
yarn patch-package package-name  # 使用yarn

运行后会在项目根目录下创建一个 patches 文件夹,并生成一个名为 package-name+version.patch 的文件。将该 patch 文件提交至版本控制中,即可在之后应用该补丁了。

以我修改的 verdaccio 为例,会生成一个 verdaccio+4.4.0.patch 的文件,内容大致如下:

diff --git a/node_modules/verdaccio/build/index.js b/node_modules/verdaccio/build/index.js
index 3a79eaa..d00974b 100644
--- a/node_modules/verdaccio/build/index.js
+++ b/node_modules/verdaccio/build/index.js
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
 });
 exports.default = void 0;

+console.log('---------------')
+
 var _bootstrap = require("./lib/bootstrap");

完成上述操作后,最后在 package.jsonscripts 中加入 "postinstall": "patch-package"

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

这样当其他同事拉下代码,运行 npm install 或是 yarn install 命令时,便会自动为依赖包打上我们的补丁了。

简单来说,这个方案的原理就是记录补丁的代码与位置,利用npm的hook( postinstall 会在npm install后触发),在安装完依赖以后,触发相应的脚本,将补丁覆盖到node_modules对应的包里。

当然,补丁是对应具体版本的,需要锁定版本号。这样的缺点是如果要升级的话,还得重新来一遍,不过不是有Bug或性能问题,通常不必追求新的版本。

pnpm patch

pnpm的patch自称灵感来自yarn的类似命令。由于yarn v2可能走了邪路,我们就不介绍了。

首先,执行 pnpm patch <pkg name>@<version> 。该命令会将指定的软件包提取到一个可以随意编辑的临时目录中。

完成修改后, 运行 pnpm patch-commit <path> (是之前提取的临时目录,这个临时目录会长到你根本记不住,不过不用担心,命令行里会有完备的提示) 以生成一个补丁文件,并提供 patchedDependencies 字段注册到你的项目中。

比如,我想修改一个is-even的包:

pnpm patch is-even  
You can now edit the following folder: /private/var/folders/sq/0jfgh1js6cs8_31df82hx3jw0000gn/T/29ba74c7c7ffd7aa157831c6436d3738

Once you're done with your changes, run "pnpm patch-commit /private/var/folders/sq/0jfgh1js6cs8_31df82hx3jw0000gn/T/29ba74c7c7ffd7aa157831c6436d3738"

按照提示,打开这个文件夹,加一行代码:

执行上面控制台的提示:

pnpm patch-commit /private/var/folders/sq/0jfgh1js6cs8_31df82hx3jw0000gn/T/e103de90617a18eee7942d1df35a2c48
Packages: -1
-
Progress: resolved 5, reused 6, downloaded 0, added 1, done

这时你会发现package.json中多了一段内容:

"pnpm": {
    "patchedDependencies": {
      "is-even@1.0.0": "patches/is-even@1.0.0.patch"
    }
}

根目录下,也多了个文件夹patches,打开以后,你就能找到添加的代码:

打开node_modules/is-even/index.js,可以看到已经多了我们添加的代码:

删除node_modules,重新pnpm i安装依赖,仍然与现在一样,这就代表成功了。

整个流程下来,我们看得出来相比于patch-package,要稍微复杂点儿,但也是可以接受的。

注意:patches目录是一定得提交到git的。

换日方案

上面说过,如果要修改的代码较多,或者不具备修改条件,这时就需要修改源码。到GitHub上找到npm包的源码,Fork该项目,修改代码后,再修改包名,重新发布,比如你要修改的包是 lodash ,可以修改为 awesome-lodash ,在应用代码中更换引用。

本来这个方案没什么好说的,但有一种情况,如果你修改的是个底层包,也就是说并不是你的应用代码中直接引用的,而是你引用的npm包A所依赖的,甚至可能同时被包B依赖的,这时就比较尴尬了,你不可能再去修改A和B的源码,那就太不值当了。

pnpm提供了一种别名(Aliases)的能力。

假设你发布了一个名为 awesome-lodash 的新包,并使用 lodash 作为别名来安装它:

pnpm add lodash@npm:awesome-lodash

不需要更改代码,所有的lodash引用都被解析到了awesome-lodash。就这么简单,上面说的问题就解决了。

再说点儿题外话,有时你会想要在项目中使用一个包的两个不同版本,很简单:

pnpm add lodash1@npm:lodash@1
pnpm add lodash2@npm:lodash@2

现在,您可以通过 require('lodash1') 引入第一个版本的 lodash 并通过 require('lodash2') 引入第二个。

与pnpm的钩子结合使用功能会更加强大,比如你想将 node_modules 里所有的 lodash 引用也替换为 awesome-lodash ,你可以用下面的 .pnpmfile.cjs 轻松实现:

function readPackage(pkg) {
  if (pkg.dependencies && pkg.dependencies.lodash) {
    pkg.dependencies.lodash = 'npm:awesome-lodash@^1.0.0'
  }
  return pkg
}

module.exports = {
  hooks: {
    readPackage
  }
}

pnpm功能非常强大,后面我会再详细写篇文章介绍下。

总结

在开发过程中发现npm包的Bug,首先向原作者提交issue或Fork代码修改后提交合并请求。但遇到不活跃或拒绝修改的情况,项目等待时间会很长。这时可以使用补丁方案或换日方案进行解决。

补丁方案中,如果是npm或yarn v1,可以使用patch-package工具包处理;如果是yarn v2或pnpm,可以使用各自的patch命令。

换日方案,则是修改源码,发布新的npm包后,利用pnpm的别名功能,将所有依赖原npm包的地方,全部替换为新的包。

这种场景在日常开发中还是比较常见的,这里为大家提供一种思路。当然,如果真是个Bug,别忘了提issue或PR,为开源贡献自己的一份力量,在与作者的沟通交流中,相信你也能受益匪浅。

上一篇
👔 技术负责人如何应对工作中的频频被打断
下一篇
🚑️ npm前员工自曝生态内部存在严重bug | 附避坑指南