当前位置: 首页 > news >正文

修改第三方npm包

文章目录

  • 一、前言
  • 二、补丁方案
    • 2.1、`patch-package`
    • 2.2、`pnpm patch`
  • 三、换日方案
  • 四、总结
  • 五、最后

一、前言

在开发过程中,发现某个npm包有Bug,应该怎么办?可以试试下面这2种方案:

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

二、补丁方案

2.1、patch-package

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

它支持npmyarn 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命令时,便会自动为依赖包打上我们的补丁了。

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

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

2.2、pnpm patch

pnpmpatch自称灵感来自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"

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

img

执行上面控制台的提示:

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,打开以后,你就能找到添加的代码:

img

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

img

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

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

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

三、换日方案

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

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

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,首先向原作者提交issueFork代码修改后提交合并请求。但遇到不活跃或拒绝修改的情况,项目等待时间会很长。这时可以使用补丁方案或换日方案进行解决。

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

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

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

五、最后

本人每篇文章都是一字一句码出来,希望对大家有所帮助,多提提意见。顺手来个三连击,点赞👍收藏💖关注✨,一起加油☕

相关文章:

修改第三方npm包

文章目录 一、前言二、补丁方案2.1、patch-package2.2、pnpm patch 三、换日方案四、总结五、最后 一、前言 在开发过程中&#xff0c;发现某个npm包有Bug&#xff0c;应该怎么办&#xff1f;可以试试下面这2种方案&#xff1a; 代码量少&#xff0c;可以直接修改npm包代码的&…...

Redis性能优化:关键配置和最佳实践

大家好&#xff0c;我是升仔 Redis作为一个高性能的键值存储系统&#xff0c;在现代应用架构中扮演着至关重要的角色。性能优化是Redis部署与维护中的一个关键环节。本文将从关键配置、持久化配置、实践场景和异常处理配置等方面&#xff0c;详细介绍如何优化Redis的性能。 关…...

华为数通方向HCIP-DataCom H12-831题库(多选题:241-249)

第241题 (NEW) 以下哪些操作可能会影响客户网络的正常运行? A、从设备上下载日志 B、软件升级 C、路由协议配置变更 D、debug核心交换机上转发的所有IP报文 答案:ABCD 解析: 第242题 对于防火墙的默认安全区 Trust 和 Untrust 的说法,正确的有 A、从 Trust 区域访问 Untr…...

typeorm联表查询:副表json格式放到主表字段下或多个副表字段并列主表字段

实体类字段不做映射&#xff0c;typeorm实现联查查询 1、副表json格式放到主表字段下 //goods表和member表联表&#xff0c;关系goods.id member.uid&#xff0c;member表数据json对象格式放到主表userInfo下 //leftJoinAndMapOne配合getMany实现 const builder await getCo…...

Flume采集日志存储到HDFS

1 日志服务器上配置Flume,采集本地日志文件&#xff0c;发送到172.19.115.96 的flume上进行聚合&#xff0c;如日志服务器有多组&#xff0c;则在多台服务器上配置相同的配置 # Name the components on this agent a1.sources r1 a1.sinks k1 a1.channels c1# Describe/con…...

redis—String字符串

目录 前言 1.字符串数据类型 2.常见命令 3.典型应用场景 前言 字符串类型是Redis最基础的数据类型&#xff0c;关于字符串需要特别注意: 1)首先Redis中所有的键的类型都是字符串类型&#xff0c;而且其他几种数据结构也都是在字符串类似基础.上构建的&#xff0c;例如列表…...

三相电机转差率为负值的情形

1.电机开始发电的特征 注意&#xff0c;电机因为有输入频率对原始旋转磁场的影响&#xff0c;在正常工作时&#xff0c;应该处于稳态&#xff0c;因为旋转磁场决定了这个系统的运转方向和运转的大致频率区间。它会处于力矩平衡态。但是&#xff0c;如果&#xff0c;此时电机处…...

关于Dark Frost 僵尸网络对游戏行业进行DDoS攻击的动态情报

一、基本内容 近期&#xff0c;一种名为Dark Frost 的新型僵尸网络被发现正在对游戏行业发起分布式拒绝服务攻击&#xff08;DDoS)。目标包括游戏公司、游戏服务器托管提供商、在线流媒体甚至和网络信息安全攻击者直接交互的其他游戏社区成员。截至2023年2月&#xff0c;僵尸网…...

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、相关的学习链接 前言&#xff1a;最近在学习前端补齐我的软件技能树&#xff0c;最近简单总结一下 1、学习路线 基本&#xff1a;vue3、ts(js)、 vite、eslint、css(动画、布局) 依赖包&#xff1a;vue-router、vue-i18…...

Vue实现响应式布局

前提准备&#xff1a;响应式布局有两种方法&#xff0c;看自己想要哪种。 方法一&#xff1a;百分比 用百分比去写元素的宽度&#xff0c;然后让子元素撑起父元素的高度 .parent {width: 50%; }.child {width:100%;height:100px; } 方法二&#xff1a;vh、vw vw、vh是基于视…...

linux:下载、网络请求、端口

一&#xff1a;ping命令 可以通过ping命令,检查指定的网络服务器是否是可联通状态 语法: ping [-c num] ip或主机名 1、选项&#xff1a;-c,检查的次数&#xff0c;不使用-c选项&#xff0c;将无限次数持续检查 2、参数&#xff1a;ip或主机名&#xff0c;被检查的服务器的…...

182.【2023年华为OD机试真题(C卷)】敏感字段加密(字符串的分割、替换和拼接实现JavaPythonC++JS)

请到本专栏顶置查阅最新的华为OD机试宝典 点击跳转到本专栏-算法之翼:华为OD机试 🚀你的旅程将在这里启航!本专栏所有题目均包含优质解题思路,高质量解题代码,详细代码讲解,助你深入学习,深度掌握! 文章目录 【2023年华为OD机试真题(C卷)】敏感字段加密(字符串…...

新版IDEA中Git的使用(三)

说明&#xff1a;前面介绍了在新版IDEA中Git的基本操作、分支操作&#xff0c;本文介绍一下在新版IDEA中&#xff0c;如何回滚代码&#xff1b; 分以下三个阶段来介绍&#xff1a; 未Commit的文件&#xff1b; 已经Commit&#xff0c;但未push的文件&#xff1b; 已经push的…...

node - koa 获取 Content-Type: text/plain 的数据

目录 1&#xff0c;Content-Type2&#xff0c;koa 获取请求的数据 1&#xff0c;Content-Type Content-Type HTTP 标头用于设置资源的类型&#xff0c;常用的有3个&#xff1a; application/jsonapplication/x-www-form-urlencoded&#xff0c;form 表单提交的格式。multipar…...

树形结构

树形结构广泛存在于客观世界中&#xff0c;如族谱、目录、社会组织、各种事物的分类等&#xff0c;都可用树形结构表示。树形结构在计算机领域应用广泛&#xff0c;如操作系统中的目录结构&#xff1b;源程序编译时&#xff0c;可用树表示源程序的语法结构&#xff1b;在数据库…...

《C++避坑神器·二十四》简单搞懂json文件的读写之根据键值对读写Json

c11 json解析库nlohmann/json.hpp文件整个代码由一个头文件组成 json.hpp&#xff0c;没有子项目&#xff0c;没有依赖关系&#xff0c;没有复杂的构建系统&#xff0c;使用起来非常方便。 json.hpp库在文章末尾下载 读写主要有两种方式&#xff0c;第一种根据键值对读写&…...

SQL进阶理论篇(二十一):基于SQLMap的自动化SQL注入

文章目录 简介获取当前数据库和用户信息获取MySQL中的所有数据库名称查询wucai数据库中的所有数据表查看heros数据表中的所有字段查询heros表中的英雄信息总结参考文献 简介 从上一小节&#xff0c;可以发现&#xff0c;如果我们编写的代码存在着SQL注入的漏洞&#xff0c;后果…...

xtu oj 1055 整数分类

Description 按照下面方法对整数x进行分类&#xff1a;如果x是一个个位数&#xff0c;则x属于x类&#xff1b;否则将x的各位上的数码累加&#xff0c;得到一个新的x&#xff0c;依次迭代&#xff0c;可以得到x的所属类。比如说24&#xff0c;246&#xff0c;则24的类别数是6&a…...

(2023|CVPR,Corgi,偏移扩散,参数高斯分布,弥合差距)用于文本到图像生成的偏移扩散

Shifted Diffusion for Text-to-image Generation 公众&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 或直接进 Q 交流群&#xff1a;922230617 获取资料&#xff09; 目录 0. 摘要 1. 简介 2. 方法 2.1 偏移扩散 3. 实验 3.1 无监督文本到图像生成 3.2 无…...

基于Keel-Kit的GitOps自动化:轻量级镜像更新与部署实践

1. 项目概述&#xff1a;一个为现代应用交付而生的“舵手工具箱”如果你和我一样&#xff0c;长期在云原生和微服务架构的浪潮里扑腾&#xff0c;那你一定对“应用交付”这四个字背后的复杂性深有体会。从代码提交到最终服务上线&#xff0c;中间横亘着构建、打包、部署、配置、…...

任务跟踪系统排名怎么看?8款企业常用工具对比

本文将深入对比8款任务跟踪系统和项目管理软件&#xff1a;Worktile、PingCode、Jira、Asana、monday.com、ClickUp、Trello、Microsoft Project。一、任务跟踪系统和项目管理软件有什么区别1、任务跟踪系统解决“事情有没有人跟、有没有进展”任务跟踪系统的核心价值&#xff…...

【NotebookLM政治学研究加速器】:20年政治理论研究员亲授5大高阶用法,告别文献综述低效时代

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;NotebookLM政治学研究辅助的范式革命 传统政治学研究长期依赖人工文献综述、手工编码与静态模型推演&#xff0c;面临信息过载、理论验证滞后与跨文本语义关联薄弱等结构性瓶颈。NotebookLM 作为基于引…...

ROS2实战:在Ubuntu 22.04上配置思岚A2激光雷达与Humble环境

1. 环境准备与硬件连接 第一次在Ubuntu 22.04上配置思岚A2激光雷达时&#xff0c;我踩过不少坑。现在把这些经验整理成保姆级教程&#xff0c;帮你避开那些让人抓狂的报错。首先需要确认你的开发环境&#xff1a;一台安装好Ubuntu 22.04的电脑&#xff08;建议物理机&#xff0…...

【无人机控制】一维环境下LQR与PID控制在无人机悬停控制中的对比分析附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码及仿真咨询…...

如何快速上手网易游戏NPK文件解包工具:新手3步完整教程

如何快速上手网易游戏NPK文件解包工具&#xff1a;新手3步完整教程 【免费下载链接】unnpk 解包网易游戏NeoX引擎NPK文件&#xff0c;如阴阳师、魔法禁书目录。 项目地址: https://gitcode.com/gh_mirrors/un/unnpk 你是否对网易游戏如《阴阳师》、《魔法禁书目录》中的…...

基于LLM的智能GA4数据分析代理:架构、部署与实战优化

1. 项目概述与核心价值 最近在折腾一个挺有意思的开源项目&#xff0c;叫 Synter-Media-AI/google-analytics-agent 。乍一看名字&#xff0c;你可能觉得这又是一个把Google Analytics数据导出来做可视化的工具&#xff0c;市面上这种工具一抓一大把。但实际深入把玩之后&am…...

一站式Steam Deck控制器配置方案:Windows平台完整游戏体验指南

一站式Steam Deck控制器配置方案&#xff1a;Windows平台完整游戏体验指南 【免费下载链接】steam-deck-windows-usermode-driver A windows usermode controller driver for the steam deck internal controller. 项目地址: https://gitcode.com/gh_mirrors/st/steam-deck-w…...

不使用void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)增强代码的层级结构注意事项

这是正常用cube Max生成的代码&#xff0c;这里以设置编码器为例。 GPIO初始化函数放在HAL_TIM_Encoder_MspInit这个回调函数中。代码正常运行/* TIM3 init function */ void MX_TIM3_Init(void) {TIM_Encoder_InitTypeDef sConfig {0};TIM_MasterConfigTypeDef sMasterConfig…...

别再只会用StegSolve了!深入理解LSB隐写原理,手写Python脚本提取隐藏信息

从像素到秘密&#xff1a;手写Python脚本破解LSB隐写的核心技术 当你面对一张看似普通的图片&#xff0c;是否曾想过它可能隐藏着重要信息&#xff1f;在CTF竞赛和数字取证领域&#xff0c;LSB&#xff08;最低有效位&#xff09;隐写术是最基础却最常被忽视的技术之一。大多数…...