该配置由 Modern.js Builder 提供,更多信息可参考 output.assetsRetry。
Object
output.assetsRetry
用于配置资源加载失败时的重试逻辑。配置类型如下:
export type AssetsRetryHookContext = {
times: number;
domain: string;
url: string;
tagName: string;
};
export type AssetsRetryOptions = {
type?: string[];
domain?: string[];
max?: number;
test?: string | ((url: string) => boolean);
crossOrigin?: boolean | 'anonymous' | 'use-credentials';
inlineScript?: boolean;
onRetry?: (options: AssetsRetryHookContext) => void;
onSuccess?: (options: AssetsRetryHookContext) => void;
onFail?: (options: AssetsRetryHookContext) => void;
};
由于该能力会往 HTML 中注入额外的一些运行时代码,因此我们默认关闭了该能力,如果需要开启该能力,你可以添加以下配置:
export default {
output: {
assetsRetry: {},
},
};
当你开启该能力后,assetsRetry
的默认配置如下:
export const defaultAssetsRetryOptions: AssetsRetryOptions = {
type: ['script', 'link', 'img'],
domain: [],
max: 3,
test: '',
crossOrigin: false,
onRetry: () => {},
onSuccess: () => {},
onFail: () => {},
};
同时你也可以使用以下的配置项,来定制你的重试逻辑。
string[]
[]
指定资源加载失败时的重试域名列表。在 domain
数组中,第一项是当前使用的域名,后面几项为备用域名。当某个域名的资源请求失败时,Builder 会在数组中找到该域名,并替换为数组的下一个域名。
比如:
export default {
output: {
assetsRetry: {
domain: ['https://cdn1.com', 'https://cdn2.com', 'https://cdn3.com'],
},
},
};
添加以上配置后,当 cdn1.com
域名的资源加载失败时,请求域名会自动降级到 cdn2.com
。
如果 cdn2.com
的资源也请求失败,则会继续请求 cdn3.com
。
string[]
['script', 'link', 'img']
用于指定需要进行重试的 HTML 标签类型。默认会处理 script 标签、link 标签和 img 标签,对应 JS 代码、CSS 代码和图片。
比如只对 script 标签和 link 标签进行处理:
export default {
output: {
assetsRetry: {
type: ['script', 'link'],
},
},
};
number
3
单个资源的最大重试次数。比如:
export default {
output: {
assetsRetry: {
max: 5,
},
},
};
string | ((url: string) => boolean) | undefined
undefined
匹配资源 URL 的正则表达式或函数,默认匹配所有资源。比如:
export default {
output: {
assetsRetry: {
test: /cdn\.example\.com/,
},
},
};
undefined | boolean | 'anonymous' | 'use-credentials'
与 html.crossorigin 一致
在发起资源重新请求时,Builder 会重新创建 <script>
标签,此选项可以设置这些标签的 crossorigin
属性。
默认情况下,assetsRetry.crossOrigin
的值会与 html.crossorigin
配置项保持一致,无须额外配置。如果你需要对重新创建的标签进行单独配置,可以使用该选项,比如:
export default {
output: {
assetsRetry: {
crossOrigin: true,
},
},
};
undefined | (options: AssetsRetryHookContext) => void
资源重试时的回调函数。比如:
export default {
output: {
assetsRetry: {
onRetry: ({ times, domain, url, tagName }) => {
console.log(
`Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}`,
);
},
},
},
};
undefined | (options: AssetsRetryHookContext) => void
资源重试成功时的回调函数。比如:
export default {
output: {
assetsRetry: {
onSuccess: ({ times, domain, url, tagName }) => {
console.log(
`Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}`,
);
},
},
},
};
undefined | (options: AssetsRetryHookContext) => void
资源重试超过最大重试次数时的回调函数。比如:
export default {
output: {
assetsRetry: {
onFail: ({ times, domain, url, tagName }) => {
console.log(
`Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}`,
);
},
},
},
};
boolean
true
是否将 assetsRetry
的运行时 JavaScript 代码内联到 HTML 文件中。
如果你不希望在 HTML 文件中插入相关代码,可以将 assetsRetry.inlineScript
设置为 false
:
export default {
output: {
assetsRetry: {
inlineScript: false,
},
},
};
添加以上配置后,assetsRetry
的运行时代码会被抽取为一个独立的 assets-retry.[version].js
文件,并输出到产物目录下。
这种方式的弊端在于,assets-retry.[version].js
自身有加载失败的可能性。如果出现这种情况,静态资源重试的逻辑就无法生效。因此,我们更推荐将运行时代码内联到 HTML 文件中。
当你使用 assetsRetry
时,Builder 会向 HTML 中注入一段运行时代码,并将 assetsRetry
配置的内容序列化,插入到这段代码中,因此你需要注意:
assetsRetry
中配置敏感信息,比如内部使用的 token。onRetry
,onSuccess
,onFail
中引用函数外部的变量或方法。onRetry
,onSuccess
,onFail
中使用有兼容性问题的语法,因为这些函数会被直接内联到 HTML 中。以下是一个错误示例:
import { someMethod } from 'utils';
export default {
output: {
assetsRetry: {
onRetry() {
// 错误用法,包含了敏感信息
const privateToken = 'a-private-token';
// 错误用法,使用了外部的方法
someMethod(privateToken);
},
},
},
};
以下场景 assetsRetry
可能无法生效:
如果你的工程是微前端应用(比如 Garfish 子应用),那么 assetsRetry
可能无法生效,因为微前端子应用通常不是基于 <script>
标签直接加载的。
如果你需要对微前端场景的资源加载进行重试,请联系微前端框架的开发者,以寻找相应的解决方案。
目前 assetsRetry
无法对动态 import 资源生效,该功能正在支持中。
assetsRetry
通过监听页面 error 事件来获悉当前资源是否加载失败需要重试。因此,如果自定义模版中的资源执行早于 assetsRetry
,那 assetsRetry
无法监听到该资源加载失败的事件,故无法 retry。
如果想要 assetsRetry
对自定义模版中的资源生效,可参考 自定义插入示例 来修改 html.inject 配置和自定义模版。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>custom template</title>
+ <%= htmlWebpackPlugin.tags.headTags %>
<script src="//example.com/assets/a.js"></script>
</head>
<body>
<div id="root" />
+ <%= htmlWebpackPlugin.tags.bodyTags %>
</body>
</html>