使用 force-resolutions 强制锁定 npm/yarn 依赖版本

在前端项目中,我们常常遇到间接依赖版本冲突、漏洞依赖未及时修复、预发版本不稳定等问题 。当这些问题出现在依赖树深层 ,而你无法直接控制依赖版本时,force-resolutions 是一种非常实用的解决方案。


什么是 force-resolutions

force-resolutions 是一个工具,此软件包修改 package-lock.json 以强制安装一组传递依赖项(依赖项的依赖项)的指定版本。

它的作用:

  • 修复第三方包引入了错误版本的依赖
  • 强制降级/升级不兼容的依赖版本
  • 快速规避临时问题(如 beta 版、破坏性更新)

工作原理简述

  • 你在 package.json 中配置 "resolutions" 字段
  • 安装 force-resolutions,在 preinstall 阶段运行
  • 它会修改 package-lock.jsonyarn.lock 中的依赖版本,使其符合你设定的 resolution

适用场景举例

  1. 某个依赖引用了漏洞版本的 lodash,但你不能直接升级它
  2. 某个 npm 包引用了错误的 beta 包(例如 @rolldown/[email protected]
  3. 多个插件依赖 tslib 但版本不一致导致重复打包

安装与配置

安装依赖

css 复制代码
npm install force-resolutions --save-dev

配置 package.json

添加 resolutions 字段来声明你想强制替换的依赖版本

perl 复制代码
{
  "resolutions": {
    "@rolldown/pluginutils": "1.0.0-beta.8"
  },
  "scripts": {
    "preinstall": "npx force-resolutions"
  }
}

⚠️ 注意:force-resolutions 必须放在 preinstall,否则 lock 文件不会被改写。


示例:统一 tslib 版本为 2.6.2

json 复制代码
{
  "resolutions": {
    "tslib": "2.6.2"
  },
  "scripts": {
    "preinstall": "npx force-resolutions"
  }
}

当你 npm install 时,force-resolutions 会:

  • 修改 package-lock.json 中所有 tslib 版本为 2.6.2
  • 然后再进行实际安装

yarn用户更简单!

如果你使用的是 Yarn(v1):

json 复制代码
{
  "resolutions": {
    "tslib": "2.6.2"
  }
}

直接运行 yarn install 即可,无需额外安装 force-resolutions,这是 Yarn 原生支持的功能。


注意事项

  1. force-resolutions基于 lock 文件操作的 ,修改后应提交 package-lock.json
  2. 对于 pnpm 用户,该工具不适用(pnpm 有自己独特的锁定机制)
  3. resolutions 不支持通配符,必须明确指定完整依赖名
  4. 每次运行 npm install 前,preinstall 会自动确保 resolution 生效

为什么不直接用 overrides

npm 在 v8.3+ 引入了 overrides 功能,用法类似:

perl 复制代码
"overrides": {
  "@rolldown/pluginutils": "1.0.0-beta.8"
}

但:

  • overrides 只在 npm >= 8.3 有效
  • 它是 纯 npm 机制,不兼容 Yarn、pnpm
  • force-resolutions 更通用,兼容老项目(特别是 Yarn 项目)

pnpm 用户

对于 pnpm 用户 ,使用 force-resolutions 是不兼容的 ------ 因为 pnpm 的依赖管理机制和 npm/yarn 有显著不同,它不使用 node_modules 扁平结构,也不修改 package-lock.json,所以:

pnpm 无法使用 force-resolutions

但 pnpm 本身提供了 官方推荐的替代方案,叫做:


pnpm.overrides ------ 官方方式强制依赖版本

pnpm v7+ 开始,你可以在 package.json 中添加:

perl 复制代码
{
  "pnpm": {
    "overrides": {
      "@rolldown/pluginutils": "1.0.0-beta.8"
    }
  }
}

然后运行:

复制代码
pnpm install

pnpm 会:

  • 强制使用你指定的版本
  • .pnpm-lock.yaml 中锁定它
  • 对所有依赖树生效

示例:修复 @rolldown/pluginutils 问题

perl 复制代码
{
  "pnpm": {
    "overrides": {
      "@rolldown/pluginutils": "1.0.0-beta.8"
    }
  }
}

如果你还需要修复多级依赖中的 tslib 等版本冲突,也可以这样:

json 复制代码
{
  "pnpm": {
    "overrides": {
      "tslib": "2.6.2",
      "some-lib > react": "^18.2.0"
    }
  }
}

支持嵌套(A > B)格式,可以精确覆盖特定依赖路径下的版本。


🧩 附加建议

  1. 使用 .npmrc 锁定 pnpm 版本(例如 monorepo 工程):

    ini 复制代码
    [email protected]
  2. CI 中添加 pnpm install --frozen-lockfile 保障依赖版本一致性

  3. 不要手动修改 .pnpm-lock.yaml,统一通过 overrides 管理冲突版本


总结

特性 force-resolutions yarn resolutions npm overrides
是否适用于 npm ✅(>=8.3)
是否适用于 yarn ✅(原生)
修改 lock 文件
支持多项目 monorepo
支持深度 patch

参考资料


最佳实践建议

  • 优先使用 yarn 原生 resolutions(如在 monorepo 项目)
  • 如果是 npm 且版本 < 8.3,使用 force-resolutions 配合 preinstall
  • 项目 CI 中应校验 lock 是否被污染,避免 resolution 被破坏
  • 加上 .nvmrc/engines 锁定 node/npm/yarn 版本,确保一致性

实战

下面以开发中遇到的一个例子来展示。 我们需要修改package.json,增加scripts和resolutins配置,格式如下。

json 复制代码
{
    "scripts": {
        "preinstall": "npx force-resolutions"
    },
    "resolutions": {
        "@xxx/xxx": "1.0.0"
    }
}

我们在使用jsx时,运行项目是报错。报Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/chenbitao/Developer/github/antdv-vue-admin/node_modules/@rolldown/pluginutils/dist/esm/index.js' imported from /Users/chenbitao/Developer/github/antdv-vue-admin/node_modules/@vitejs/plugin-vue-jsx/dist/index.mjs

shell 复制代码
% npm run dev
npm info using [email protected]
npm info using [email protected]

> [email protected] dev
> vite

failed to load config from /Users/chenbitao/Developer/github/antdv-vue-admin/vite.config.ts
error when starting dev server:
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/chenbitao/Developer/github/antdv-vue-admin/node_modules/@rolldown/pluginutils/dist/esm/index.js' imported from /Users/chenbitao/Developer/github/antdv-vue-admin/node_modules/@vitejs/plugin-vue-jsx/dist/index.mjs
    at finalizeResolution (node:internal/modules/esm/resolve:265:11)
    at moduleResolve (node:internal/modules/esm/resolve:933:10)
    at defaultResolve (node:internal/modules/esm/resolve:1169:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:542:12)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:510:25)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:239:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:96:40)
    at link (node:internal/modules/esm/module_job:95:36)

通过search node_modules插件发现依赖@rolldown/pluginutils下面没有js文件。

www.npmjs.com/package/@ro...

再访问npm上对应的的版本,发现在一天前npm有被publish一次,但是列表可以看到一个月前发布的。

列表没有取最新的时间,但详情页表示确实推送过,就是这次推送,导致了历史的版本内容消失,本地重新安装依赖后就报错。

而最新的版本,也是昨天推送的,可以标记为弃用,但还是选择了直接重新推一个空的仓库,可能是作者故意为之,想将仓库里有重大问题的仓库代码直接删除。

www.npmjs.com/package/@ro...

找到问题再解决就很容易了,因为我使用的是npm,所以我选择使用force-resolutions

这里的包名要写对,版本号规则和dependencies一致,支持指定版本范围版本。

json 复制代码
{
  // 其他配置
  "scripts": {
    "preinstall": "npx force-resolutions"
  },
  "resolutions": {
    "@rolldown/pluginutils": "1.0.0-beta.18"
  }
  // 其他配置
}
bash 复制代码
# 这里使用-y是
npm install

输出以下内容就表示成功,可以再回去去检查node_modulespackage-lock.json中是否有修改成功。

shell 复制代码
% npm install
npm info using [email protected]
npm info using [email protected]
npm http fetch POST 200 https://mirrors.tencent.com/npm/-/npm/v1/security/advisories/bulk 630ms

> [email protected] preinstall
> npx force-resolutions

npm info using [email protected]
npm info using [email protected]
npm http fetch GET 200 https://mirrors.tencent.com/npm/force-resolutions 264ms (cache revalidated)
Applying forced resolutions:
@rolldown/pluginutils => 1.0.0-beta.18
Finished applying forced resolutions.
npm info ok

up to date, audited 566 packages in 3s

160 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
npm info ok

再次运行项目,问题解决。

相关推荐
duanyuehuan22 分钟前
Vue 组件定义方式的区别
前端·javascript·vue.js
veminhe26 分钟前
HTML5简介
前端·html·html5
洪洪呀27 分钟前
css上下滚动文字
前端·css
搏博1 小时前
基于Vue.js的图书管理系统前端界面设计
前端·javascript·vue.js·前端框架·数据可视化
掘金安东尼2 小时前
前端周刊第419期(2025年6月16日–6月22日)
前端·javascript·面试
bemyrunningdog2 小时前
AntDesignPro前后端权限按钮系统实现
前端
重阳微噪2 小时前
Data Config Admin - 优雅的管理配置文件
前端
Hilaku2 小时前
20MB 的字体文件太大了,我们把 Icon Font 压成了 10KB
前端·javascript·css
fs哆哆2 小时前
在VB.net中,文本插入的几个自定义函数
服务器·前端·javascript·html·.net
专注VB编程开发20年2 小时前
C# .NET多线程异步记录日声,队列LOG
java·开发语言·前端·数据库·c#