修改第三方npm包
文章目录
- 一、前言
- 二、补丁方案
- 2.1、`patch-package`
- 2.2、`pnpm patch`
- 三、换日方案
- 四、总结
- 五、最后
一、前言
在开发过程中,发现某个npm包有Bug,应该怎么办?可以试试下面这2种方案:
- 代码量少,可以直接修改
npm包代码的,考虑补丁方案。- 代码量多,或者
npm包代码是压缩混淆过的,不具备修改条件。修改源码后,再修改包名,重新发布,在应用代码中更换引用。为叙文方便,我将这种方案命名为换日方案(偷天换日,李代桃僵)。
二、补丁方案
2.1、patch-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.json的scripts中加入"postinstall": "patch-package"。
"scripts": {"postinstall": "patch-package"
}
这样当其他同事拉下代码,运行npm install或是yarn install命令时,便会自动为依赖包打上我们的补丁了。
简单来说,这个方案的原理就是记录补丁的代码与位置,利用
npm的hook(postinstall会在npm install后触发),在安装完依赖以后,触发相应的脚本,将补丁覆盖到node_modules对应的包里。当然,补丁是对应具体版本的,需要锁定版本号。这样的缺点是如果要升级的话,还得重新来一遍,不过不是有
Bug或性能问题,通常不必追求新的版本。
2.2、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/29ba74c7c7ffd7aa157831c6436d3738Once 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}
}
四、总结
在开发过程中发现npm包的Bug,首先向原作者提交issue或Fork代码修改后提交合并请求。但遇到不活跃或拒绝修改的情况,项目等待时间会很长。这时可以使用补丁方案或换日方案进行解决。
补丁方案中,如果是npm或yarn v1,可以使用patch-package工具包处理;如果是yarn v2或pnpm,可以使用各自的patch命令。
换日方案,则是修改源码,发布新的npm包后,利用pnpm的别名功能,将所有依赖原npm包的地方,全部替换为新的包。
这种场景在日常开发中还是比较常见的,这里为大家提供一种思路。当然,如果真是个Bug,别忘了提issue或PR,为开源贡献自己的一份力量,在与作者的沟通交流中,相信你也能受益匪浅。
五、最后
本人每篇文章都是一字一句码出来,希望对大家有所帮助,多提提意见。顺手来个三连击,点赞👍收藏💖关注✨,一起加油☕
相关文章:
修改第三方npm包
文章目录 一、前言二、补丁方案2.1、patch-package2.2、pnpm patch 三、换日方案四、总结五、最后 一、前言 在开发过程中,发现某个npm包有Bug,应该怎么办?可以试试下面这2种方案: 代码量少,可以直接修改npm包代码的&…...
Redis性能优化:关键配置和最佳实践
大家好,我是升仔 Redis作为一个高性能的键值存储系统,在现代应用架构中扮演着至关重要的角色。性能优化是Redis部署与维护中的一个关键环节。本文将从关键配置、持久化配置、实践场景和异常处理配置等方面,详细介绍如何优化Redis的性能。 关…...
华为数通方向HCIP-DataCom H12-831题库(多选题:241-249)
第241题 (NEW) 以下哪些操作可能会影响客户网络的正常运行? A、从设备上下载日志 B、软件升级 C、路由协议配置变更 D、debug核心交换机上转发的所有IP报文 答案:ABCD 解析: 第242题 对于防火墙的默认安全区 Trust 和 Untrust 的说法,正确的有 A、从 Trust 区域访问 Untr…...
typeorm联表查询:副表json格式放到主表字段下或多个副表字段并列主表字段
实体类字段不做映射,typeorm实现联查查询 1、副表json格式放到主表字段下 //goods表和member表联表,关系goods.id member.uid,member表数据json对象格式放到主表userInfo下 //leftJoinAndMapOne配合getMany实现 const builder await getCo…...
Flume采集日志存储到HDFS
1 日志服务器上配置Flume,采集本地日志文件,发送到172.19.115.96 的flume上进行聚合,如日志服务器有多组,则在多台服务器上配置相同的配置 # Name the components on this agent a1.sources r1 a1.sinks k1 a1.channels c1# Describe/con…...
redis—String字符串
目录 前言 1.字符串数据类型 2.常见命令 3.典型应用场景 前言 字符串类型是Redis最基础的数据类型,关于字符串需要特别注意: 1)首先Redis中所有的键的类型都是字符串类型,而且其他几种数据结构也都是在字符串类似基础.上构建的,例如列表…...
三相电机转差率为负值的情形
1.电机开始发电的特征 注意,电机因为有输入频率对原始旋转磁场的影响,在正常工作时,应该处于稳态,因为旋转磁场决定了这个系统的运转方向和运转的大致频率区间。它会处于力矩平衡态。但是,如果,此时电机处…...
关于Dark Frost 僵尸网络对游戏行业进行DDoS攻击的动态情报
一、基本内容 近期,一种名为Dark Frost 的新型僵尸网络被发现正在对游戏行业发起分布式拒绝服务攻击(DDoS)。目标包括游戏公司、游戏服务器托管提供商、在线流媒体甚至和网络信息安全攻击者直接交互的其他游戏社区成员。截至2023年2月,僵尸网…...
MongoDB数据库本地部署并结合内网穿透实现navicat公网访问
文章目录 前言1. 安装数据库2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射2.3 测试随机公网地址远程连接 3. 配置固定TCP端口地址3.1 保留一个固定的公网TCP端口地址3.2 配置固定公网TCP端口地址3.3 测试固定地址公网远程访问 前言 MongoDB是一个基于分布式文件存储的数…...
前端学习笔记
文章目录 1、学习路线2、token的安全储存方案3、跨域4、相关的学习链接 前言:最近在学习前端补齐我的软件技能树,最近简单总结一下 1、学习路线 基本:vue3、ts(js)、 vite、eslint、css(动画、布局) 依赖包:vue-router、vue-i18…...
Vue实现响应式布局
前提准备:响应式布局有两种方法,看自己想要哪种。 方法一:百分比 用百分比去写元素的宽度,然后让子元素撑起父元素的高度 .parent {width: 50%; }.child {width:100%;height:100px; } 方法二:vh、vw vw、vh是基于视…...
linux:下载、网络请求、端口
一:ping命令 可以通过ping命令,检查指定的网络服务器是否是可联通状态 语法: ping [-c num] ip或主机名 1、选项:-c,检查的次数,不使用-c选项,将无限次数持续检查 2、参数:ip或主机名,被检查的服务器的…...
182.【2023年华为OD机试真题(C卷)】敏感字段加密(字符串的分割、替换和拼接实现JavaPythonC++JS)
请到本专栏顶置查阅最新的华为OD机试宝典 点击跳转到本专栏-算法之翼:华为OD机试 🚀你的旅程将在这里启航!本专栏所有题目均包含优质解题思路,高质量解题代码,详细代码讲解,助你深入学习,深度掌握! 文章目录 【2023年华为OD机试真题(C卷)】敏感字段加密(字符串…...
新版IDEA中Git的使用(三)
说明:前面介绍了在新版IDEA中Git的基本操作、分支操作,本文介绍一下在新版IDEA中,如何回滚代码; 分以下三个阶段来介绍: 未Commit的文件; 已经Commit,但未push的文件; 已经push的…...
node - koa 获取 Content-Type: text/plain 的数据
目录 1,Content-Type2,koa 获取请求的数据 1,Content-Type Content-Type HTTP 标头用于设置资源的类型,常用的有3个: application/jsonapplication/x-www-form-urlencoded,form 表单提交的格式。multipar…...
树形结构
树形结构广泛存在于客观世界中,如族谱、目录、社会组织、各种事物的分类等,都可用树形结构表示。树形结构在计算机领域应用广泛,如操作系统中的目录结构;源程序编译时,可用树表示源程序的语法结构;在数据库…...
《C++避坑神器·二十四》简单搞懂json文件的读写之根据键值对读写Json
c11 json解析库nlohmann/json.hpp文件整个代码由一个头文件组成 json.hpp,没有子项目,没有依赖关系,没有复杂的构建系统,使用起来非常方便。 json.hpp库在文章末尾下载 读写主要有两种方式,第一种根据键值对读写&…...
SQL进阶理论篇(二十一):基于SQLMap的自动化SQL注入
文章目录 简介获取当前数据库和用户信息获取MySQL中的所有数据库名称查询wucai数据库中的所有数据表查看heros数据表中的所有字段查询heros表中的英雄信息总结参考文献 简介 从上一小节,可以发现,如果我们编写的代码存在着SQL注入的漏洞,后果…...
xtu oj 1055 整数分类
Description 按照下面方法对整数x进行分类:如果x是一个个位数,则x属于x类;否则将x的各位上的数码累加,得到一个新的x,依次迭代,可以得到x的所属类。比如说24,246,则24的类别数是6&a…...
(2023|CVPR,Corgi,偏移扩散,参数高斯分布,弥合差距)用于文本到图像生成的偏移扩散
Shifted Diffusion for Text-to-image Generation 公众:EDPJ(添加 VX:CV_EDPJ 或直接进 Q 交流群:922230617 获取资料) 目录 0. 摘要 1. 简介 2. 方法 2.1 偏移扩散 3. 实验 3.1 无监督文本到图像生成 3.2 无…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
