Webpack MF Shared 依赖:仅配 requiredVersion 时的版本选择细节与坑点

68 阅读3分钟

在上一篇博客深入解析 Webpack Module Federation 的 Shared 依赖版本协商机制,我们已经详细的分析了各种不同shared配置之下,版本协商是如何进行的。

然后有不少同发现仅配 requiredVersion 时的版本选择并不是简单的“谁先加载了就用谁”,今天想通过这篇文章解答一下


仅配 requiredVersion 时的版本选择细节

var loadVersion = (scopeName, scope, key, eager, requiredVersion, fallback) => {
  if (!exists(scope, key))
    return useFallback(scopeName, key, fallback);
  var satisfyingVersion = findSatisfyingVersion(scope, key, requiredVersion, eager);
  if (satisfyingVersion)
    return get(satisfyingVersion);
  warn(getInvalidVersionMessage(...));
  return get(findLatestVersion(scope, key, eager));
};

var findSatisfyingVersion = (scope, key, requiredVersion, eager) => {
  var versions = eager ? eagerOnly(scope[key]) : scope[key];
  var key = Object.keys(versions).reduce((a, b) => {
    if (!satisfy(requiredVersion, b)) return a;
    return !a || versionLt(a, b) ? b : a;
  }, 0);
  return key && versions[key];
};

关键认知点:

  • findSatisfyingVersion 会在所有可用的版本中,选出“满足 requiredVersion 且版本号最大的那个”
  • 若没有任何版本能满足 requiredVersion,loadVersion 还会兜底选最新(findLatestVersion)

这很关键:不是“谁先注册谁先用”,而是总是倾向于用“满足 semver 且最大的那个”


实验结论验证

基于以下依赖结构:

  • host 应用:引用 axios@1.6.8,并 shared 配置 { axios: { requiredVersion: '1.6.8' } }
  • remote 子应用:引用 axios@1.10.0,并 shared 配置 { axios: { requiredVersion: '^1.5.0' } }

实测结果如下:

  • host 首先加载时,matching 的只有 1.6.8,就先用它
  • remote 需要加载自己的 1.10.0,而 1.10.0 比 ^1.5.0 匹配范围更大、版本号也高,于是 remote 实际会加载自己的 1.10.0
  • 两端都用各自版本,符合 runtime 选择“最大满足条件”的版本的策略

反直觉却合理的机制

这种做法其实有点反直觉。
很多开发者下意识以为:只要第一个满足 requiredVersion 的就直接用那个,但 Webpack MF 选择了在符合 semver 范围下尽可能用最大版本

原因:

  • 满足 semver 的最大版本,理论上具备旧特性的兼容性,也能兼容新特性,利于多远端版本协同时减少重大兼容隐患。
  • 若存在 breaking change 危险,建议配合 strictVersion。

最佳实践建议

  1. 明确主版本统一:MF 项目强烈建议所有 host/remote 尽量依赖同一主版本(如 axios@1.x)。
  2. 充分测试:如果允许 shared 时存在多版本,需在本地和 CI 全面覆盖兼容性场景。
  3. 如需严格一致,启用 strictVersion: true,确保 runtime 强制版本一致,否则直接报错,拒绝混用。

总结

Webpack Module Federation 的 shared 依赖协商机制并非简单“谁先用谁的”,而是综合按 semver 匹配尽可能选择最大版本。这一点对于维护复杂微前端架构时确保依赖一致性和新旧兼容,至关重要!

如果你还在为版本选择疑惑,建议直接研读源码并实际搭配配置进行测试,才能真正理解自己的项目在微前端环境下是如何运行的。如果有更复杂的多次 fallback、多个 remote 组合情况,也欢迎交流讨论!


参考阅读: