团队协作开发中如何修改node_modules

98 阅读3分钟

背景

在开发过程中常常遇见node modules中的 A 包不完全满足使用场景或者有bug,常见的解决方式如下

1. 直接在 A 包找到代码块,进行源代码修改

    优点:简单直接
    缺点:只能本地自己使用、下次npm iA 包的代码又恢复原状

2. 把 A 包的源码拖出来自己维护,全局修改该包的引用地址,再针对该包做代码优化

    优点:能应急使用 
    缺点:很暴力且事后维护成本较高

3. 把问题提给作者,等待发布

    优点:不用操心了
    缺点:做好石沉大海或修复周期很长的准备

patch-package

patch-package 相当于是在给A包打补丁及记录修改记录,就算重新npm i 根据补丁对A包重新进行修改,但对npm包入口是build后的文件就不可行

第一步 安装依赖
    npm i patch-package

    yarn add patch-package postinstall-postinstall

使用yarn的话需要这个postinstall-postinstall

为什么 yarn 要用 postinstall-postinstall 的官方解释

image.png

总结下就是确保在yarn remove时依旧能保持更正代码

第二步 修改 node_modules

拿lodash当A包举例 修改lodash的isEqual方法

  function baseIsEqual(value, other, bitmask, customizer, stack) {
      //此处三等改为两等
      if (value == other) {
        return true;
      }
      if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
        return value !== value && other !== other;
      }
      return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
    }
    function isEqual(value, other) {
        console.log("记录下进来了");
        return baseIsEqual(value, other);
    }
第三步 生成修改文件
    npx patch-package lodash

这个时候你的项目根目录下会出现patches这个目录,里面会出现一个lodash的补丁文件,大致内容如下

index 4131e93..8020ee5 100644
--- a/node_modules/lodash/lodash.js
+++ b/node_modules/lodash/lodash.js
@@ -3307,7 +3307,8 @@
      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
      */
     function baseIsEqual(value, other, bitmask, customizer, stack) {
-      if (value === other) {
+
+      if (value == other) {
         return true;
       }
       if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
@@ -11597,6 +11598,7 @@
      * // => false
      */
     function isEqual(value, other) {
+      console.log("记录下进来了");
       return baseIsEqual(value, other);
     }
第四步修改 package.json

在package.json的script中增加

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

ps:在 scripts 字段里可以自定义的脚本以及使用一些特殊脚本,这里的作用是每次npm i时 会去读取patches目录下的补丁文件,并将补丁打到对应的包里

此时可以重新装一下依赖,测试一下结果,即便重装依赖,我们对 node_modules 下代码的修改还是被 patch-package 还原并最终生效。再把patches目下的补丁文件上传到git,同事也可以同步修改的包,至此我们便完成一次临时打补丁的操作

特定的 scripts

对于以下脚本,npm 支持 package.json 文件的 scripts 默认命令字段:

  • prepublish: 在打包并发布包之前运行,以及在没有任何参数的本地 npm 安装之前运行。 (见下文)
  • prepare: 在打包和发布包之前运行,在没有任何参数的本地 npm install 上运行,以及安装 git 依赖项时(见下文)。 这是在 preublish 之后运行,但是在 preublishOnly 之前运行。
  • prepublishOnly: 在包准备和打包之前运行,仅限于npm发布。 (见下文。)
  • prepack: 在打包 tarball 之前运行(在 npm packnpm publish,以及安装 git 依赖项时)
  • postpack: 在生成 tarball 之后运行并移动到其最终目标。
  • publishpostpublish: 在包发布后运行。
  • preinstall: 在安装软件包之前运行。
  • installpostinstall: 安装包后运行。
  • preuninstalluninstall: 在卸载软件包之前运行。
  • postuninstall: 在卸载软件包之后运行。
  • preversion: 在改变包版本之前运行。
  • version: 改变包版本后运行,但提交之前。
  • postversion: 改变包版本后运行,然后提交。
  • pretesttestposttest: 由 npm test 命令运行。
  • prestopstoppoststop: 由 npm stop 命令运行。
  • prestartstartpoststart: 由 npm start 命令运行。
  • prerestartrestartpostrestart: 由 npm restart 命令运行。 注意:如果没有提供重启脚本,npm restart 将运行 stop 和start 脚本。
  • preshrinkwrapshrinkwrappostshrinkwrap: 由 npm shrinkwrap 命令运行。

参考文档:npm docs.