如何使用patch-package给npm包打补丁

0 阅读1小时+

一、背景

在移动应用开发中,轮播是一种很常见的效果,我们项目采用的是RN跨平台技术,RN的轮播我们直接使用的是第三方插件:react-native-snap-carousel。不过,当我们在项目中使用的时候却发现Android和iOS的表现不一致:stackoverflow.com/questions/6…

image.png

通过分析发现,react-native-snap-carousel的源码有对android和iOS进行分开处理,那怎么办呢?首先我们想到的是将源码拉取下来,使用源码依赖,不过这种不方面后面的CI/CD,后面通过查找资料发现可以使用npm补丁包的方式来解决这种问题。

二、npm补丁包

安装插件

首先,安装 patch-package:

npm i patch-package --save-dev

创建补丁

直接在项目根目录下的 node_modules 文件夹中找到要修改依赖包的相关文件,然后回到根目录执行如下命令制作补丁文件。

# npm > 5.2
npx patch-package package-name

# yarn 
yarn patch-package package-name

package-name 就是要修改的依赖包名。执行完成后,会在项目根目录的 patches 目录中创建补丁文件 package-name+0.44.0.patch(0.44.0 是依赖包版本),这个补丁需要提交到代码仓库中。

以下是创建补丁时的一些可选参数:

  • --use-yarn:patch-package 默认是根据项目中的 lockfile 来决定使用 npm 还是 yarn,如果两种都有,则使用 npm,可以通过这个参数启用 yarn。

  • --exclude :创建补丁文件时,忽略与正则表达式匹配的路径,路径相对于要修改的依赖包的根目录,默认: package\.json$。

  • --include :与 --exclude 相反,创建补丁文件时仅考虑与正则表达式匹配的路径,默认: .*。

  • --case-sensitive-path-filtering:使 --include 或 --exclude 中使用的正则表达式区分大小写。

  • --patch-dir:指定放置补丁文件的目录。

嵌套补丁

支持修改依赖包的依赖包,比如 node_modules/package/node_modules/another-package,通过 / 分隔。

npx patch-package package/another-package

# scoped packages
npx patch-package @my/package/@my/other-package

更新补丁

将制作生成的补丁文件拷贝到根目录下的patches文件夹中。

image.png 示例中的补丁包内容如下:

diff --git a/node_modules/react-native-snap-carousel/src/utils/animations.ts b/node_modules/react-native-snap-carousel/src/utils/animations.ts
index bf1c50f..a438f1a 100644
--- a/node_modules/react-native-snap-carousel/src/utils/animations.ts
+++ b/node_modules/react-native-snap-carousel/src/utils/animations.ts
@@ -1,7 +1,7 @@
 import { Platform, Animated } from 'react-native';
 import type { CarouselProps } from 'src/carousel/types';
 
-const IS_ANDROID = Platform.OS === 'android';
+const IS_ANDROID = false;
 
 // Get scroll interpolator's input range from an array of slide indexes
 // Indexes are relative to the current active slide (index 0)

添加指令

在 package.json 的 scripts 中加入 "postinstall": "patch-package",后续执行 npm install 或 yarn install 命令时,会自动为依赖包打补丁了。

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

查看结果

再次运行项目,然后打开node_modules下的文件,会发现代码已经替换成了补丁包的内容。

使用patch-package实现npm补丁包时有两点需要注意:

  1. 要修改的依赖包版本最好是固定的,即不会自动升级版本,这样可以避免自动升级后导致补丁包失效,从而打包失败影响原有功能;

  2. 协同开发的同学需要重新安装一下依赖;