重试插件

重试插件为 Module Federation 提供强大的资源加载失败重试机制,当远程模块或资源加载失败时,自动进行重试以确保应用的稳定性。

功能特性

  • 自动重试: 资源加载失败时自动重试,提高应用稳定性
  • 域名轮换: 支持多个备用域名,自动切换到可用的域名
  • 缓存破坏: 通过添加查询参数避免浏览器缓存影响重试结果
  • 灵活配置: 支持自定义重试次数、延迟时间和回调函数

安装

npm install @module-federation/retry-plugin

迁移指南

从 v0.18.x 到 v0.19.x

插件配置已经简化。旧的 fetchscript 配置对象已被弃用:

// ❌ 旧方式(已弃用)
RetryPlugin({
  fetch: {
    url: 'http://localhost:2008/not-exist-mf-manifest.json',
    fallback: () => 'http://localhost:2001/mf-manifest.json',
  },
  script: {
    url: 'http://localhost:2001/static/js/async/src_App_tsx.js',
    customCreateScript: (url, attrs) => { /* ... */ },
  }
})

// ✅ 新方式
RetryPlugin({
  retryTimes: 3,
  retryDelay: 1000,
  domains: ['http://localhost:2001'],
  manifestDomains: ['http://localhost:2001'],
  addQuery: ({ times, originalQuery }) => `${originalQuery}&retry=${times}`,
})

使用方法

方式一:构建插件中使用

rspack.config.ts
import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';
import { defineConfig } from '@rsbuild/core';

export default defineConfig({
  plugins: [
    pluginReact(),
    pluginModuleFederation({
      runtimePlugins: [
        path.join(__dirname, './src/runtime-plugin/retry.ts'),
      ],
    }),
  ],
});
// ./src/runtime-plugin/retry.ts
import { RetryPlugin } from '@module-federation/retry-plugin';
const retryPlugin = () => RetryPlugin({
  retryTimes: 3,
  retryDelay: 1000,
  manifestDomains: ['https://domain1.example.com', 'https://domain2.example.com'],
  domains: ['https://cdn1.example.com', 'https://cdn2.example.com'],
  addQuery: ({ times, originalQuery }) => `${originalQuery}&retry=${times}`,
  onRetry: ({ times, url }) => console.log('retry', times, url),
  onSuccess: ({ url }) => console.log('success', url),
  onError: ({ url }) => console.log('error', url),
})
export default retryPlugin;

方式二:运行时注册

import { createInstance, loadRemote } from '@module-federation/enhanced/runtime';
import { RetryPlugin } from '@module-federation/retry-plugin';

const mf = createInstance({
  name: 'federation_consumer',
  remotes: [],
  plugins: [
    RetryPlugin({
      retryTimes: 3,
      retryDelay: 1000,
      manifestDomains: ['https://domain1.example.com', 'https://domain2.example.com'],
      domains: ['https://cdn1.example.com', 'https://cdn2.example.com'],
      addQuery: ({ times, originalQuery }) => `${originalQuery}&retry=${times}`,
      onRetry: ({ times, url }) => console.log('retry', times, url),
      onSuccess: ({ url }) => console.log('success', url),
      onError: ({ url }) => console.log('error', url),
    }),
  ],
});

配置参数

基础配置

retryTimes

  • 类型:number
  • 可选
  • 重试的次数,默认为 3

retryDelay

  • 类型:number
  • 可选
  • 重试间隔时间(毫秒),默认为 1000

高级配置

domains

  • 类型:string[]
  • 可选
  • 备用域名列表,用于域名轮换重试,默认为空数组

addQuery

  • 类型:boolean | ((context: { times: number; originalQuery: string }) => string)
  • 可选
  • 是否在重试时添加查询参数,默认为 false
  • 当为函数时,接收重试次数和原始查询字符串,返回新的查询字符串

fetchOptions

  • 类型:RequestInit
  • 可选
  • 自定义 fetch 请求选项,默认为空对象

manifestDomains

  • 类型:string[]
  • 可选
  • 用于 mf-manifest.json 资源的域名轮换列表(优先级高于 domains)。当配置了 manifestDomains 时,插件在获取 mf-manifest.json 等清单资源的重试中,会优先按 manifestDomains 顺序进行域名切换;其他资源仍使用 domains

回调函数

onRetry

  • 类型:({ times, domains, url, tagName }: { times?: number; domains?: string[]; url?: string; tagName?: string }) => void
  • 可选
  • 重试时触发的回调函数
  • 参数:times 重试次数,domains 域名列表,url 请求URL,tagName 资源类型

onSuccess

  • 类型:({ domains, url, tagName }: { domains?: string[]; url?: string; tagName?: string; }) => void
  • 可选
  • 重试成功时触发的回调函数
  • 参数:domains 域名列表,url 请求URL,tagName 资源类型

onError

  • 类型:({ domains, url, tagName }: { domains?: string[]; url?: string; tagName?: string; }) => void
  • 可选
  • 重试最终失败时触发的回调函数
  • 参数:domains 域名列表,url 请求URL,tagName 资源类型

详细说明

重试机制

插件会在资源加载失败时自动进行重试,重试次数由 retryTimes 参数控制。例如:

  • retryTimes: 3 表示总共尝试 4 次(1次初始尝试 + 3次重试)
  • 每次重试前会等待 retryDelay 毫秒

域名轮换

当配置了 domains 参数时,插件会在重试时自动切换到下一个域名:

const retryPlugin = RetryPlugin({
  domains: [
    'https://cdn1.example.com',
    'https://cdn2.example.com', 
    'https://cdn3.example.com'
  ],
});

重试顺序:

  1. 首次尝试:原始 URL
  2. 第1次重试:切换到 cdn2.example.com
  3. 第2次重试:切换到 cdn3.example.com
  4. 第3次重试:切换到 cdn1.example.com

缓存破坏

通过 addQuery 参数可以在重试时添加查询参数,避免浏览器缓存影响:

const retryPlugin = RetryPlugin({
  addQuery: true, // 添加 ?retryCount=1, ?retryCount=2 等
});

也可以使用自定义函数:

const retryPlugin = RetryPlugin({
  addQuery: ({ times, originalQuery }) => {
    return `${originalQuery}&retry=${times}&timestamp=${Date.now()}`;
  },
});

回调函数

插件提供了三个回调函数,让你可以监控重试过程:

const retryPlugin = RetryPlugin({
  onRetry: ({ times, domains, url, tagName }) => {
    console.log(`第 ${times} 次重试,使用域名: ${domains}, URL: ${url}`);
  },
  onSuccess: ({ domains, url, tagName }) => {
    console.log(`重试成功,域名: ${domains}, URL: ${url}`);
  },
  onError: ({ domains, url, tagName }) => {
    console.log(`重试失败,域名: ${domains}, URL: ${url}`);
  },
});

回调函数参数说明:

  • times: 当前重试次数(从1开始)
  • domains: 当前使用的域名列表
  • url: 当前请求的URL
  • tagName: 资源类型('fetch' 或 'script')

使用场景

1. CDN 故障容错

const retryPlugin = RetryPlugin({
  retryTimes: 2,
  domains: [
    'https://cdn1.example.com',
    'https://cdn2.example.com',
    'https://cdn3.example.com'
  ],
  addQuery: true,
});

2. 网络不稳定环境

const retryPlugin = RetryPlugin({
  retryTimes: 5,
  retryDelay: 2000,
  onRetry: ({ times }) => {
    console.log(`网络不稳定,第 ${times} 次重试`);
  },
});

3. 监控和日志

const retryPlugin = RetryPlugin({
  onRetry: ({ times, url }) => {
    // 发送重试事件到监控系统
    analytics.track('resource_retry', { times, url });
  },
  onError: ({ url }) => {
    // 记录最终失败
    logger.error('Resource load failed after all retries', { url });
  },
});

注意事项

  1. 性能考虑: 过多的重试次数会增加加载时间,建议根据实际网络环境调整
  2. 域名配置: 确保 domains 中的域名都指向相同的资源
  3. 缓存策略: 使用 addQuery 时注意 CDN 的缓存策略
  4. 错误处理: 重试失败后,原始错误会被抛出,需要在上层进行错误处理

错误码

插件使用标准的 Module Federation 错误码:

  • RUNTIME_008: 资源加载失败,触发重试机制