patch-package 实现原理:如何保存恢复 node_modules 下的代码改动?

开发 前端
patches 文件的生成是在临时目录生成 package.json,下载依赖,生成一个 commit,然后把改动的代码复制过去,两者做 gif diff,就可以生成 patches 文件。

有时候我们需要修改 node_modules 下的一些代码,但是 node_modules 不会提交到 git 仓库,改动保存不下来,怎么办呢?

这时候可以用 patch-package 这个工具。

比如我对 node_modules 下的 acorn 代码做了一些修改:

加了一个 a.js 的文件:

图片

在项目目录下执行 npx patch-package acorn 之后,就会生成这样一个目录:

图片

在 patches 目录下的 xx.patch 文件里记录着对这个包的改动。

这个 patches 目录是可以提交到 git 仓库的,然后再次把项目拉下来的时候,执行下 npx patch-package 就会应用这次改动。

可以把它配到 postintsll 里,每次安装完依赖自动跑。

图片

这样能保证每次拉取下来的代码都包含了对 node_modules 的改动。

如何使用我们学会了,那它是怎么实现的呢?

探究它的实现原理要分为两各方面,一个是 patches 文件怎么生成的,一个是 patches 文件怎么被应用的。

patches 文件怎么生成的

看 patches 文件的内容就能看出来这是 git 的 diff:

图片

确实,patch-package 就是依赖 git diff 实现的 patches 文件生成。

首先 patch-package 会创建一个临时目录:

图片

然后在这个目录写入一个 package.json 文件,dependencies 就是命令行参数指定的包名:

图片

我们去这个目录看一下:

图片

确实,是有这样一个 package.json 的。

然后它会在这个目录下执行 yarn install 或者 npm install(patch-package 现在不支持 pnpm):

图片

图片

之后就进行 git 的 init、add、commit,生成一个基础的 commit。

图片

然后把现在 node_modules 目录下的这个被修改过的包复制过去:

图片

之后再 git add,然后执行 git diff,就能拿到改动的 diff:

图片

这不就是 patches 文件的内容么:

图片

然后写到 patches 目录即可

图片

patches 文件的生成还是挺简单的,就是在临时目录下创建了一个基础 commit,然后把新的内容复制过去,通过 git diff 生成的 patches 内容。

那应用 patches 的内容是怎么实现的呢?

patches 如何被应用的?

我又对 acorn 目录下的文件做了些修改,生成的 patches 文件是包含了增删改的:

图片

图片

图片

patches 文件里记录了对哪几行做了新增,哪几行做了删除,哪几行做了修改。

如果人工应用这个 patches 文件的话,不就是找到对应文件的对应行数,做反向的操作就可以了么?

没错,patch-package 也是这样实现的,不过是自动进行的:

它读取 patches 文件之后会进行 parse:

图片

这个 parse 的实现就是对每一行的字符串做判断,进行不同的处理:

图片

最终能得到一个包含 diff 信息的对象,包含了对什么文件的哪些行做了什么修改:

图片

之后对不同的类型做不同的操作就可以了:

图片

这样就把 patches 文件里的改动应用到了 node_modules 下的包里。

总结

当我们需要对 node_modules 下的代码做改动的时候,可以通过 patch-package xxx 生成 patches 文件,它可以被提交到 git 仓库,然后再拉下来的代码就可以通过 patch-package 来应用改动。

实现原理要分为两部分来看:

patches 文件的生成是在临时目录生成 package.json,下载依赖,生成一个 commit,然后把改动的代码复制过去,两者做 gif diff,就可以生成 patches 文件。

patches 文件的应用则是 patch-package 自己实现了它的 parse,拿到对什么文件的哪些行做什么修改的信息,之后根据不同做类型做不同的文件操作就可以了。

整体看下来,这个小工具的原理还是挺清晰的,不过 parse patch 文件那部分还是有些麻烦的,当你需要解析 git diff 信息的时候,也可以参考下它的实现。

责任编辑:武晓燕 来源: 神光的编程秘籍
相关推荐

2022-09-19 13:57:24

文件前端代码

2020-07-16 14:00:38

node_module文件前端

2022-06-14 09:04:55

前端npm

2021-09-03 08:21:20

前端代码模块

2017-11-01 15:13:49

TensorFlow神经网络深度学习

2021-11-16 19:37:03

缓存

2019-10-08 11:10:18

React自动保存前端

2014-05-14 00:50:18

JoyentNode

2018-12-27 10:00:37

Windows10Office文档

2023-12-07 08:07:47

Node流程代码

2009-09-01 18:06:06

c#保存窗体状态

2022-04-26 08:32:36

CSS前端

2015-12-11 11:49:19

java

2015-12-11 11:39:15

.net代码

2017-10-23 10:13:18

IO底层虚拟

2022-01-17 07:50:37

Linux Patch项目

2018-04-22 00:01:43

JavaScript Node 语言

2010-08-12 13:32:08

DB2数据库备份

2022-08-10 09:02:08

SwiftDecodable

2017-03-22 14:23:58

Java HashMa实现原理
点赞
收藏

51CTO技术栈公众号