# 重试插件
重试插件为 Module Federation 提供强大的资源加载失败重试机制,当远程模块或资源加载失败时,自动进行重试以确保应用的稳定性。
## 功能特性
- **自动重试**: 资源加载失败时自动重试,提高应用稳定性
- **域名轮换**: 支持多个备用域名,自动切换到可用的域名
- **缓存破坏**: 通过添加查询参数避免浏览器缓存影响重试结果
- **灵活配置**: 支持自定义重试次数、延迟时间和回调函数
## 安装
```bash
npm install @module-federation/retry-plugin
```
## 迁移指南
### 从 v0.18.x 到 v0.19.x
插件配置已经简化。旧的 `fetch` 和 `script` 配置对象已被弃用:
```ts
// ❌ 旧方式(已弃用)
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}`,
})
```
## 使用方法
### 方式一:构建插件中使用
```ts title="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'),
],
}),
],
});
```
```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;
```
### 方式二:运行时注册
```ts
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` 参数时,插件会在重试时自动切换到下一个域名:
```javascript
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` 参数可以在重试时添加查询参数,避免浏览器缓存影响:
```javascript
const retryPlugin = RetryPlugin({
addQuery: true, // 添加 ?retryCount=1, ?retryCount=2 等
});
```
也可以使用自定义函数:
```javascript
const retryPlugin = RetryPlugin({
addQuery: ({ times, originalQuery }) => {
return `${originalQuery}&retry=${times}×tamp=${Date.now()}`;
},
});
```
### 回调函数
插件提供了三个回调函数,让你可以监控重试过程:
```javascript
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 故障容错
```javascript
const retryPlugin = RetryPlugin({
retryTimes: 2,
domains: [
'https://cdn1.example.com',
'https://cdn2.example.com',
'https://cdn3.example.com'
],
addQuery: true,
});
```
### 2. 网络不稳定环境
```javascript
const retryPlugin = RetryPlugin({
retryTimes: 5,
retryDelay: 2000,
onRetry: ({ times }) => {
console.log(`网络不稳定,第 ${times} 次重试`);
},
});
```
### 3. 监控和日志
```javascript
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`: 资源加载失败,触发重试机制