巧用 package.json overrides / resolutions

semver 语义化版本控制

首先,快速的带大家回顾一下 semver 语义化版本控制

我们的 npm 模块都是严格遵循这套版本控制的

格式为 [major, minor, patch] 例如 react@18.2.0

大版本就是 18, 次版本为 2,补丁版本则为 0

大版本表示有 breakChange ,可能会有不向前兼容的 api

次版本则为一些小改动

补丁版本为一些 bug 的修复

次版本和补丁版都是向前兼容的版本

除此之外,在 package.json 中我们还可以看到一些符号

json 复制代码
  "dependencies": {
    // ^ 表示允许更新次版本和补丁版本,
    // 例如可以更新到 18.2.1 / 18.3.0
    // 但是不会更新到 19.0.0
    "react": "^18.2.0",
    // ~ 表示允许更新补丁版本,
    // 例如可以更新到 18.2.1
    // 但是不会更新到 18.3.0 / 19.0.0
    "react-dom": "~18.2.0",
    // 不加任何符号 表示准确的匹配某个版本
    "lodash": "4.17.21"
  },

现在回到正题 介绍一下 package.json 中的 overrides / resolution 字段

场景一:安装依赖冲突

我们初始化一个项目

yarn create vite npm --template react-ts

先用 npm 来介绍,后面针对 yarn 补充一些不同的地方

除去一些无用的依赖,我们得到一个最小的 package.json

json 复制代码
{
  "name": "npm",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.43",
    "@types/react-dom": "^18.2.17",
    "@vitejs/plugin-react": "^4.2.1",
    "typescript": "^5.2.2",
    "vite": "^5.0.8"
  }
}

然后我们引入一个用于 json 可视化的库

npm install react-json-view

这个时候就会得到一个报错

查看报错原因或者 react-json-view 的 package.json 的 peerDependencies

json 复制代码
"peerDependencies": {
    "react": "^17.0.0 || ^16.3.0 || ^15.5.4",
    "react-dom": "^17.0.0 || ^16.3.0 || ^15.5.4"
}

www.npmjs.com/package/rea...

可以看到 我们项目的直接依赖 react 的版本是 18.2.0 不满足 react-json-view 中需要的 react 的版本

这个时候就可以引出 overrides

我们在 package.json 中加入一个新的字段 overrides

json 复制代码
  "overrides": {
    // 表示只覆盖 react-json-view 这个项目下的依赖
    "react-json-view": {
      // $ 表示跟随本项目下的react版本,即^18.2.0
      "react": "$react",
      // 当然也可以直接指定对应的重写版本 (推荐上述写法)
      "react-dom": "^18.2.0"
    }
  }

然后再运行 npm install react-json-view 就可以看到依赖被成功的安装了

运行 npm ls react-dom 查看 react-dom 在项目中依赖关系

可以看到 react-json-view 下的 react-dom 版本已经被重写了

场景二:解决一些 security bug

第二种场景则是,例如你维护了一个时间比较久的项目,

突然在某次上线前的 security scan 中 发现了一些第三方模块的漏洞,需要升级这些模块来 fix

其中,有的可能是项目的直接依赖,有的则是第三方模块的子依赖,甚至可能是很深的子依赖

这个时候,你也需要用到 overrides 来重写项目中的依赖关系

当然前提是,你得知道重写后不会破坏项目的运行

还是这个项目我们运行

npm ls semver

我们可以看到 semver 在项目中有两个并存的版本 6.x 的 和 7.x 的

例如,如果有一天在安全扫描的时候,我们被告诉 6.x 的这个版本有安全问题需要升级到最新的版本

这个时候也可以通过 overrides 来实现

json 复制代码
  "overrides": {
    "react-json-view": {
      "react": "$react",
      "react-dom": "$react-dom"
    },
    "semver": "^7.5.4"
  }

重新安装依赖,可以看到项目中所有用到 semver 的地方都被替换成了我们指定的版本

当然启动项目也是正常的

补充一些 yarn 的区别

yarn 和 npm 不同的地方在于

yarn 中重写依赖的字段不是 overrides 而是 resolutions

同时查看依赖关系的命令为 yarn list --pattern react-dom 等价于 npm ls react-dom

overrides 中可以嵌套的书写,重写某个特定模块下的子依赖 例如

json 复制代码
  "overrides": {
    "react-json-view": {
      "react": "$react",
      "react-dom": "$react-dom"
    },
  }

但是在 yarn 下 只能写成

json 复制代码
  "resolutions": {
    "react": "$react",
    "react-dom": "$react-dom"
  }
相关推荐
一个处女座的程序猿O(∩_∩)O1 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
hackeroink4 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者6 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-6 小时前
验证码机制
前端·后端
燃先生._.7 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖8 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235248 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240259 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar9 小时前
纯前端实现更新检测
开发语言·前端·javascript