修改node_modules中依赖库

4,355 阅读5分钟

之前项目中引入了一个水印插件,引入之后发现水印图层会撑开页面高度的问题,虽然提了issue,但是真的等不及等到官方更新了,直接down下来改源码走紧急修复上线了。这两天,发现同事也碰到了依赖库问题。所以从目前我或我同事们碰到的几种情况下想要修改依赖库入手,做点解决方案的小结。

改源码要慎重,建议确定要改源码之前,先完成以下的checklist:

  • 通读依赖库对应版本的文档、手册的相关API,排除自己引用错了的乌龙事件
  • 定位node_modules里对应的依赖库里的版本、API传参要求,也是排除官方文档和实际下载引用的库版本不一致,导致传参有误
  • 官方是否已修复,github上是否有相关的issue,项目中能否升级至最新版本
  • 在一个pure版本的项目应用中,应用对应版本的依赖库,排除是项目中其他内容覆盖导致依赖库失效


case 1. 依赖库有bug,要修复源码文件,但是官方维护达不到自己的时间要求

确定要修改源码了,但是时间真的紧迫,依赖库的社区不活跃,官方也没有相关的issue,整理描述重现步骤和问题反馈沟通还要花时间(但是准确描述稳定重现步骤也是帮助自己定位问题的第一步,,该花还是要花的),,基本上你真的只能自己撸起袖子去定位源码修复了。。

修复的办法,这里有两个:

1. 评估依赖库包size不大,直接像笔者之前down下来修复,替换之前引用的node_modules库地址(可以通过webpack alias,也可以是路径引入)

2. 依赖库不能轻易替换,这里推荐个小工具patch-package。就是给依赖库打个补丁,不影响依赖库正常升级,只是涉及到你修改的内容会用你的补丁替换。

实现原理:直接在依赖库中编辑修复,然后该工具会生成个临时文件夹存放对应版本的依赖库,然后和你修改的依赖库目录去进行比较,生成一个patch文件,下次在执行npm install时,该工具会将该patch合进该依赖库去。

具体操作步骤:

  1. 项目的根目录package.json下,添加npm postinstall,以便每次执行npm install时能合进所有的patch文件:

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

  2. 安装patch-package:

    npm i patch-package --save

  3. 编辑依赖库<package-name>,并执行下面命令生成patch文件:

    npx patch-package <package-name>

  4. 再执行以下命令,你就发现最新安装的包已经合进了你刚刚修改的patch文件了:

    npm install

这里如果你修改的是依赖库的package.json有点问题。。嗯。。我已经提了issue了。。

case 2. 依赖库自己引入的某个库偷偷升级了,线上环境版本太低无法兼容

嗯。。客观因素,线上环境版本被限定死了,不能轻易调整(我相信即便你反馈了,运维同学也会告诉你先找找其他解决办法,他们只求一个字,稳!别整幺蛾子)

四种参考方案:

  1. package.json中降低并固定依赖库的版本------------嗯,这个方法适用于不需要经常更新或者使用场景单一的依赖库,比如笔者一开始说的水印
  2. package.json中固定依赖库中依赖的库版本----------该方法适用于npm3版本及以下。

原理剖析:npm3把所有依赖模块路径扁平化,以便依赖模块共享。node_modules查找路径会先从当前依赖库的根目录下去查找,如果没有再往上层去查找,循环直到找到该模块或者node_modules顶层目录。如果没有该模块才会去镜像仓库拉取最新的包。

npm 5.0.x 版本及以上:可更新package.json和package-lock.json锁定拉取的依赖库源地址即可。(详情可参考这里)

   3.  升级node.js----------如果是在npm run build时,因为async await这类ES高版本的语法,导致webpack打包抛错的问题。(嗯,,如果你要升级,运维同学应该在旁边拿着刀瞅着你)

   4. 利用webpack loader对依赖库编译解析

像上面这种ES8及ES10,ES11的高级写法不被webpack识别,也因为node.js版本较低不兼容,可通过babel-loader进行转换,高阶段位可尝试自己写个loader。


case 3. 依赖库不支持目前的业务场景,要定制化

嗯。。可以看看目前依赖库是否支持扩展,如果支持度不够高,可以搞下来,根据业务扩展定制化,发布到公司的私有库下进行小范围内的共享。


当然还有些笔者觉得不是很有必要修改源码的情形:

case 1. 依赖库最新版本有问题

可以给开源社区做贡献了,提好issue,在确保回退稳定版本不会影响线上内容时,可先回退。

case 2. 依赖库有问题,但维护团队活跃

比如antd design 圣诞铲雪的彩蛋,,嗯,,官方抢修挺快的,啊哈哈哈

先暂时记录这些,to be continued...