@rsbuild/plugin-assets-retry 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -10
- package/README.zh-CN.md +120 -10
- package/dist/index.cjs +45 -33
- package/dist/index.d.ts +6 -2
- package/dist/index.js +43 -34
- package/dist/runtime/asyncChunkRetry.js +55 -34
- package/dist/runtime/asyncChunkRetry.min.js +1 -1
- package/dist/runtime/initialChunkRetry.js +75 -52
- package/dist/runtime/initialChunkRetry.min.js +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -59,33 +59,43 @@ type AssetsRetryHookContext = {
|
|
|
59
59
|
isAsyncChunk: boolean;
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
type
|
|
62
|
+
type RuntimeRetryOptions = {
|
|
63
63
|
type?: string[];
|
|
64
64
|
domain?: string[];
|
|
65
65
|
max?: number;
|
|
66
|
-
test?: string | ((url: string) => boolean);
|
|
66
|
+
test?: string | RegExp | ((url: string) => boolean);
|
|
67
67
|
crossOrigin?: boolean | 'anonymous' | 'use-credentials';
|
|
68
|
-
inlineScript?: boolean;
|
|
69
68
|
delay?: number | ((context: AssetsRetryHookContext) => number);
|
|
70
69
|
onRetry?: (context: AssetsRetryHookContext) => void;
|
|
71
70
|
onSuccess?: (context: AssetsRetryHookContext) => void;
|
|
72
71
|
onFail?: (context: AssetsRetryHookContext) => void;
|
|
73
72
|
};
|
|
73
|
+
|
|
74
|
+
type AssetsRetryOptions =
|
|
75
|
+
| ({
|
|
76
|
+
inlineScript?: boolean;
|
|
77
|
+
minify?: boolean;
|
|
78
|
+
} & RuntimeRetryOptions)
|
|
79
|
+
| {
|
|
80
|
+
inlineScript?: boolean;
|
|
81
|
+
minify?: boolean;
|
|
82
|
+
rules: RuntimeRetryOptions[];
|
|
83
|
+
};
|
|
74
84
|
```
|
|
75
85
|
|
|
76
86
|
- **Default:**
|
|
77
87
|
|
|
78
88
|
```ts
|
|
79
89
|
const defaultAssetsRetryOptions = {
|
|
90
|
+
max: 3,
|
|
80
91
|
type: ['script', 'link', 'img'],
|
|
81
92
|
domain: [],
|
|
82
|
-
max: 3,
|
|
83
|
-
test: '',
|
|
84
93
|
crossOrigin: false,
|
|
94
|
+
test: '',
|
|
85
95
|
delay: 0,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
96
|
+
addQuery: false,
|
|
97
|
+
inlineScript: true,
|
|
98
|
+
minify: rsbuildConfig.mode === 'production',
|
|
89
99
|
};
|
|
90
100
|
```
|
|
91
101
|
|
|
@@ -242,7 +252,7 @@ When set to `true`, `retry=${times}` will be added to the query when requesting,
|
|
|
242
252
|
|
|
243
253
|
When you want to customize query, you can pass a function, for example:
|
|
244
254
|
|
|
245
|
-
- **Example:** All assets requested do not contain query:
|
|
255
|
+
- **Example 1:** All assets requested do not contain query:
|
|
246
256
|
|
|
247
257
|
```js
|
|
248
258
|
pluginAssetsRetry({
|
|
@@ -254,7 +264,7 @@ pluginAssetsRetry({
|
|
|
254
264
|
});
|
|
255
265
|
```
|
|
256
266
|
|
|
257
|
-
- **Example:** If there is a query in some of the requested assets, you can read it with `originalQuery`:
|
|
267
|
+
- **Example 2:** If there is a query in some of the requested assets, you can read it with `originalQuery`:
|
|
258
268
|
|
|
259
269
|
```js
|
|
260
270
|
pluginAssetsRetry({
|
|
@@ -325,6 +335,80 @@ pluginAssetsRetry({
|
|
|
325
335
|
});
|
|
326
336
|
```
|
|
327
337
|
|
|
338
|
+
### rules
|
|
339
|
+
|
|
340
|
+
- **Type:** `RuntimeRetryOptions[]`
|
|
341
|
+
- **Default:** `undefined`
|
|
342
|
+
|
|
343
|
+
Configure multiple retry rules with different options. Each rule will be evaluated in order, and the first matching rule will be used for retry logic. This is useful when you have different retry requirements for different types of assets or domains.
|
|
344
|
+
|
|
345
|
+
When using `rules`, the plugin will:
|
|
346
|
+
|
|
347
|
+
1. Check each rule in order by `test` `domain` `type`
|
|
348
|
+
|
|
349
|
+
2. If the rule is matched, the rule's configuration will be used to retry
|
|
350
|
+
|
|
351
|
+
3. If no rule is matched, the resource will not be retried
|
|
352
|
+
|
|
353
|
+
Each rule supports all the same options as the top-level configuration, including `type`, `domain`, `max`, `test`, `crossOrigin`, `delay`, `onRetry`, `onSuccess`, and `onFail`.
|
|
354
|
+
|
|
355
|
+
- **Example 1:** Different retry strategies for different CDNs:
|
|
356
|
+
|
|
357
|
+
```js
|
|
358
|
+
pluginAssetsRetry({
|
|
359
|
+
rules: [
|
|
360
|
+
{
|
|
361
|
+
// Rule for primary CDN
|
|
362
|
+
test: /cdn1\.example\.com/,
|
|
363
|
+
domain: ['cdn1.example.com', 'cdn1-backup.example.com'],
|
|
364
|
+
max: 3,
|
|
365
|
+
delay: 1000,
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
// Rule for secondary CDN with more retries
|
|
369
|
+
test: /cdn2\.example\.com/,
|
|
370
|
+
domain: ['cdn2.example.com', 'cdn2-backup.example.com'],
|
|
371
|
+
max: 5,
|
|
372
|
+
delay: 500,
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
// Default rule for other assets
|
|
376
|
+
domain: ['default.example.com', 'default-backup.example.com'],
|
|
377
|
+
max: 2,
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
- **Example 2:** Different retry strategies for different asset types:
|
|
384
|
+
|
|
385
|
+
```js
|
|
386
|
+
pluginAssetsRetry({
|
|
387
|
+
rules: [
|
|
388
|
+
{
|
|
389
|
+
// Critical JavaScript files get more retries
|
|
390
|
+
type: ['script'],
|
|
391
|
+
// Or test: /\.js$/,
|
|
392
|
+
max: 5,
|
|
393
|
+
delay: 1000,
|
|
394
|
+
onFail: ({ url }) => console.error(`Critical JS failed: ${url}`),
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
// CSS files get fewer retries
|
|
398
|
+
test: /\.css$/,
|
|
399
|
+
max: 2,
|
|
400
|
+
delay: 500,
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
// Images get minimal retries
|
|
404
|
+
test: /\.(png|jpg|gif|svg)$/,
|
|
405
|
+
max: 1,
|
|
406
|
+
delay: 0,
|
|
407
|
+
},
|
|
408
|
+
],
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
328
412
|
## Notes
|
|
329
413
|
|
|
330
414
|
When you use Assets Retry plugin, the Rsbuild injects some runtime code into the HTML and [Rspack Runtime](https://rspack.dev/misc/glossary#runtime), then serializes the Assets Retry plugin config, inserting it into the runtime code. Therefore, you need to be aware of the following:
|
|
@@ -389,6 +473,32 @@ If you want Assets Retry plugin to work on resources in custom templates, you ca
|
|
|
389
473
|
</html>
|
|
390
474
|
```
|
|
391
475
|
|
|
476
|
+
#### Identifying retry scripts in HTML templates
|
|
477
|
+
|
|
478
|
+
The Assets Retry plugin adds a unique `data-rsbuild-assets-retry` attribute to retry scripts, allowing you to easily identify them in custom HTML templates.
|
|
479
|
+
|
|
480
|
+
You can import the attribute constant:
|
|
481
|
+
|
|
482
|
+
```js
|
|
483
|
+
import { ASSETS_RETRY_DATA_ATTRIBUTE } from '@rsbuild/plugin-assets-retry';
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
The attribute values are:
|
|
487
|
+
- `"inline"` for inline scripts (when `inlineScript: true`)
|
|
488
|
+
- `"external"` for external scripts (when `inlineScript: false`)
|
|
489
|
+
|
|
490
|
+
Example usage in HTML templates:
|
|
491
|
+
|
|
492
|
+
```html
|
|
493
|
+
<!-- Filter retry scripts -->
|
|
494
|
+
<%= htmlWebpackPlugin.tags.headTags.filter(tag => tag.attributes['data-rsbuild-assets-retry'] === 'inline') %>
|
|
495
|
+
|
|
496
|
+
<!-- Filter non-retry scripts -->
|
|
497
|
+
<%= htmlWebpackPlugin.tags.headTags.filter(tag => !tag.attributes['data-rsbuild-assets-retry']) %>
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
This allows you to place retry scripts at the top of your HTML head for optimal loading order.
|
|
501
|
+
|
|
392
502
|
## License
|
|
393
503
|
|
|
394
504
|
[MIT](./LICENSE).
|
package/README.zh-CN.md
CHANGED
|
@@ -57,33 +57,43 @@ type AssetsRetryHookContext = {
|
|
|
57
57
|
isAsyncChunk: boolean;
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
-
type
|
|
60
|
+
type RuntimeRetryOptions = {
|
|
61
61
|
type?: string[];
|
|
62
62
|
domain?: string[];
|
|
63
63
|
max?: number;
|
|
64
64
|
test?: string | ((url: string) => boolean);
|
|
65
65
|
crossOrigin?: boolean | 'anonymous' | 'use-credentials';
|
|
66
|
-
inlineScript?: boolean;
|
|
67
66
|
delay?: number | ((context: AssetsRetryHookContext) => number);
|
|
68
67
|
onRetry?: (context: AssetsRetryHookContext) => void;
|
|
69
68
|
onSuccess?: (context: AssetsRetryHookContext) => void;
|
|
70
69
|
onFail?: (context: AssetsRetryHookContext) => void;
|
|
71
70
|
};
|
|
71
|
+
|
|
72
|
+
type AssetsRetryOptions =
|
|
73
|
+
| ({
|
|
74
|
+
inlineScript?: boolean;
|
|
75
|
+
minify?: boolean;
|
|
76
|
+
} & RuntimeRetryOptions)
|
|
77
|
+
| {
|
|
78
|
+
inlineScript?: boolean;
|
|
79
|
+
minify?: boolean;
|
|
80
|
+
rules: RuntimeRetryOptions[];
|
|
81
|
+
};
|
|
72
82
|
```
|
|
73
83
|
|
|
74
84
|
- **默认值:**
|
|
75
85
|
|
|
76
86
|
```ts
|
|
77
|
-
const
|
|
87
|
+
const defaultAssetsRetryOptions = {
|
|
88
|
+
max: 3,
|
|
78
89
|
type: ['script', 'link', 'img'],
|
|
79
90
|
domain: [],
|
|
80
|
-
max: 3,
|
|
81
|
-
test: '',
|
|
82
91
|
crossOrigin: false,
|
|
92
|
+
test: '',
|
|
83
93
|
delay: 0,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
94
|
+
addQuery: false,
|
|
95
|
+
inlineScript: true,
|
|
96
|
+
minify: rsbuildConfig.mode === 'production',
|
|
87
97
|
};
|
|
88
98
|
```
|
|
89
99
|
|
|
@@ -240,7 +250,7 @@ type AddQuery =
|
|
|
240
250
|
|
|
241
251
|
当你想要自定义 query 时,可以传入一个函数,比如:
|
|
242
252
|
|
|
243
|
-
-
|
|
253
|
+
- **示例 1:** 请求的所有资源都不含 query:
|
|
244
254
|
|
|
245
255
|
```js
|
|
246
256
|
pluginAssetsRetry({
|
|
@@ -252,7 +262,7 @@ pluginAssetsRetry({
|
|
|
252
262
|
});
|
|
253
263
|
```
|
|
254
264
|
|
|
255
|
-
-
|
|
265
|
+
- **示例 2:** 当请求的某些资源中含有 query 时,可以使用 `originalQuery` 读取:
|
|
256
266
|
|
|
257
267
|
```js
|
|
258
268
|
pluginAssetsRetry({
|
|
@@ -323,6 +333,80 @@ pluginAssetsRetry({
|
|
|
323
333
|
});
|
|
324
334
|
```
|
|
325
335
|
|
|
336
|
+
### rules
|
|
337
|
+
|
|
338
|
+
- **类型:** `RuntimeRetryOptions[]`
|
|
339
|
+
- **默认值:** `undefined`
|
|
340
|
+
|
|
341
|
+
配置多个重试规则,每个规则可以有不同的选项。规则会按顺序进行评估,第一个匹配的规则将用于重试逻辑。这在你对不同类型的资源或域名有不同的重试需求时非常有用。
|
|
342
|
+
|
|
343
|
+
使用 `rules` 时,插件会:
|
|
344
|
+
|
|
345
|
+
1. 按顺序通过 `test` `domain` `type` 检查每个规则
|
|
346
|
+
|
|
347
|
+
2. 如果匹配到规则,会使用规则的配置进行重试
|
|
348
|
+
|
|
349
|
+
3. 如果没有匹配到规则,则不会重试该资源
|
|
350
|
+
|
|
351
|
+
每个规则支持与顶层配置相同的所有选项,包括 `type`、`domain`、`test`、`max`、`crossOrigin`、`delay`、`onRetry`、`onSuccess` 和 `onFail`。
|
|
352
|
+
|
|
353
|
+
- **示例 1:** 不同 CDN 的不同重试策略:
|
|
354
|
+
|
|
355
|
+
```js
|
|
356
|
+
pluginAssetsRetry({
|
|
357
|
+
rules: [
|
|
358
|
+
{
|
|
359
|
+
// 主 CDN 的规则
|
|
360
|
+
test: /cdn1\.example\.com/,
|
|
361
|
+
domain: ['cdn1.example.com', 'cdn1-backup.example.com'],
|
|
362
|
+
max: 3,
|
|
363
|
+
delay: 1000,
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
// 次要 CDN 的规则,更多重试次数
|
|
367
|
+
test: /cdn2\.example\.com/,
|
|
368
|
+
domain: ['cdn2.example.com', 'cdn2-backup.example.com'],
|
|
369
|
+
max: 5,
|
|
370
|
+
delay: 500,
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
// 其他资源的默认规则
|
|
374
|
+
domain: ['default.example.com', 'default-backup.example.com'],
|
|
375
|
+
max: 2,
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
});
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
- **示例 2:** 不同资源类型的不同重试策略:
|
|
382
|
+
|
|
383
|
+
```js
|
|
384
|
+
pluginAssetsRetry({
|
|
385
|
+
rules: [
|
|
386
|
+
{
|
|
387
|
+
// 关键 JavaScript 文件获得更多重试次数
|
|
388
|
+
test: /\.js$/,
|
|
389
|
+
// 或者 type: ['script'],
|
|
390
|
+
max: 5,
|
|
391
|
+
delay: 1000,
|
|
392
|
+
onFail: ({ url }) => console.error(`关键 JS 失败: ${url}`),
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
// CSS 文件获得较少的重试次数
|
|
396
|
+
test: /\.css$/,
|
|
397
|
+
max: 2,
|
|
398
|
+
delay: 500,
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
// 图片获得最少的重试次数
|
|
402
|
+
test: /\.(png|jpg|gif|svg)$/,
|
|
403
|
+
max: 1,
|
|
404
|
+
delay: 0,
|
|
405
|
+
},
|
|
406
|
+
],
|
|
407
|
+
});
|
|
408
|
+
```
|
|
409
|
+
|
|
326
410
|
## 注意事项
|
|
327
411
|
|
|
328
412
|
当你使用 Assets Retry 插件时,Rsbuild 会分别向 HTML 和 [Rspack Runtime](https://rspack.dev/zh/misc/glossary#runtime) 中注入运行时代码,并将 Assets Retry 插件配置的内容序列化后插入到这些代码中,因此你需要注意:
|
|
@@ -387,6 +471,32 @@ Assets Retry 插件通过监听页面 error 事件来获悉当前资源是否加
|
|
|
387
471
|
</html>
|
|
388
472
|
```
|
|
389
473
|
|
|
474
|
+
#### 在 HTML 模板中识别重试脚本
|
|
475
|
+
|
|
476
|
+
Assets Retry 插件为重试脚本添加了唯一的 `data-rsbuild-assets-retry` 属性,使您可以在自定义 HTML 模板中轻松识别它们。
|
|
477
|
+
|
|
478
|
+
您可以导入属性常量:
|
|
479
|
+
|
|
480
|
+
```js
|
|
481
|
+
import { ASSETS_RETRY_DATA_ATTRIBUTE } from '@rsbuild/plugin-assets-retry';
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
属性值包括:
|
|
485
|
+
- `"inline"` 用于内联脚本(当 `inlineScript: true` 时)
|
|
486
|
+
- `"external"` 用于外部脚本(当 `inlineScript: false` 时)
|
|
487
|
+
|
|
488
|
+
在 HTML 模板中的使用示例:
|
|
489
|
+
|
|
490
|
+
```html
|
|
491
|
+
<!-- 筛选重试脚本 -->
|
|
492
|
+
<%= htmlWebpackPlugin.tags.headTags.filter(tag => tag.attributes['data-rsbuild-assets-retry'] === 'inline') %>
|
|
493
|
+
|
|
494
|
+
<!-- 筛选非重试脚本 -->
|
|
495
|
+
<%= htmlWebpackPlugin.tags.headTags.filter(tag => !tag.attributes['data-rsbuild-assets-retry']) %>
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
这允许您将重试脚本放置在 HTML 头部的顶部以获得最佳的加载顺序。
|
|
499
|
+
|
|
390
500
|
## License
|
|
391
501
|
|
|
392
502
|
[MIT](./LICENSE).
|
package/dist/index.cjs
CHANGED
|
@@ -170,6 +170,7 @@ var __webpack_exports__ = {};
|
|
|
170
170
|
__webpack_require__.r(__webpack_exports__);
|
|
171
171
|
__webpack_require__.d(__webpack_exports__, {
|
|
172
172
|
pluginAssetsRetry: ()=>pluginAssetsRetry,
|
|
173
|
+
ASSETS_RETRY_DATA_ATTRIBUTE: ()=>ASSETS_RETRY_DATA_ATTRIBUTE,
|
|
173
174
|
PLUGIN_ASSETS_RETRY_NAME: ()=>PLUGIN_ASSETS_RETRY_NAME
|
|
174
175
|
});
|
|
175
176
|
const external_node_fs_namespaceObject = require("node:fs");
|
|
@@ -249,8 +250,9 @@ var __webpack_exports__ = {};
|
|
|
249
250
|
}
|
|
250
251
|
const src_dirname = external_node_path_default().dirname((0, external_node_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
|
|
251
252
|
const PLUGIN_ASSETS_RETRY_NAME = 'rsbuild:assets-retry';
|
|
252
|
-
|
|
253
|
-
|
|
253
|
+
const ASSETS_RETRY_DATA_ATTRIBUTE = 'data-rsbuild-assets-retry';
|
|
254
|
+
function getRuntimeOptions(userOptions, defaultCrossOrigin) {
|
|
255
|
+
const { inlineScript, minify, ...runtimeOptions } = userOptions;
|
|
254
256
|
const defaultOptions = {
|
|
255
257
|
max: 3,
|
|
256
258
|
type: [
|
|
@@ -259,18 +261,27 @@ var __webpack_exports__ = {};
|
|
|
259
261
|
'img'
|
|
260
262
|
],
|
|
261
263
|
domain: [],
|
|
262
|
-
crossOrigin:
|
|
264
|
+
crossOrigin: defaultCrossOrigin,
|
|
263
265
|
delay: 0,
|
|
264
266
|
addQuery: false
|
|
265
267
|
};
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
268
|
+
function normalizeOption(options) {
|
|
269
|
+
const result = {
|
|
270
|
+
...defaultOptions,
|
|
271
|
+
...options
|
|
272
|
+
};
|
|
273
|
+
if (!Array.isArray(result.type) || 0 === result.type.length) result.type = defaultOptions.type;
|
|
274
|
+
if (!Array.isArray(result.domain) || 0 === result.domain.length) result.domain = defaultOptions.domain;
|
|
275
|
+
if (Array.isArray(result.domain)) result.domain = result.domain.filter(Boolean);
|
|
276
|
+
return result;
|
|
277
|
+
}
|
|
278
|
+
if ('rules' in runtimeOptions) {
|
|
279
|
+
const result = runtimeOptions.rules.map((i)=>normalizeOption(i));
|
|
280
|
+
return result;
|
|
281
|
+
}
|
|
282
|
+
return [
|
|
283
|
+
normalizeOption(runtimeOptions)
|
|
284
|
+
];
|
|
274
285
|
}
|
|
275
286
|
async function getRetryCode(runtimeOptions, minify) {
|
|
276
287
|
const filename = 'initialChunkRetry';
|
|
@@ -284,27 +295,25 @@ var __webpack_exports__ = {};
|
|
|
284
295
|
const { inlineScript = true } = userOptions;
|
|
285
296
|
const getScriptPath = (environment)=>{
|
|
286
297
|
const distDir = environment.config.output.distPath.js;
|
|
287
|
-
return external_node_path_default().posix.join(distDir, "assets-retry.1-
|
|
298
|
+
return external_node_path_default().posix.join(distDir, "assets-retry.1-4-0.js");
|
|
288
299
|
};
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
300
|
+
const getDefaultValueFromRsbuildConfig = (config)=>{
|
|
301
|
+
var _config_output_minify;
|
|
302
|
+
const minify = 'boolean' == typeof config.output.minify ? config.output.minify : null == (_config_output_minify = config.output.minify) ? void 0 : _config_output_minify.js;
|
|
303
|
+
return {
|
|
304
|
+
crossorigin: config.html.crossorigin,
|
|
305
|
+
minify: Boolean(minify) && 'production' === config.mode
|
|
292
306
|
};
|
|
293
|
-
if (void 0 === options.crossOrigin) options.crossOrigin = config.html.crossorigin;
|
|
294
|
-
if (void 0 === options.minify) {
|
|
295
|
-
var _config_output_minify;
|
|
296
|
-
const minify = 'boolean' == typeof config.output.minify ? config.output.minify : null == (_config_output_minify = config.output.minify) ? void 0 : _config_output_minify.js;
|
|
297
|
-
options.minify = minify && 'production' === config.mode;
|
|
298
|
-
}
|
|
299
|
-
return options;
|
|
300
307
|
};
|
|
301
308
|
if (inlineScript) api.modifyHTMLTags(async ({ headTags, bodyTags }, { environment })=>{
|
|
302
|
-
const
|
|
303
|
-
const runtimeOptions = getRuntimeOptions(
|
|
304
|
-
const code = await getRetryCode(runtimeOptions,
|
|
309
|
+
const { minify, crossorigin } = getDefaultValueFromRsbuildConfig(environment.config);
|
|
310
|
+
const runtimeOptions = getRuntimeOptions(userOptions, crossorigin);
|
|
311
|
+
const code = await getRetryCode(runtimeOptions, minify);
|
|
305
312
|
headTags.unshift({
|
|
306
313
|
tag: "script",
|
|
307
|
-
attrs: {
|
|
314
|
+
attrs: {
|
|
315
|
+
[ASSETS_RETRY_DATA_ATTRIBUTE]: 'inline'
|
|
316
|
+
},
|
|
308
317
|
children: code
|
|
309
318
|
});
|
|
310
319
|
return {
|
|
@@ -319,7 +328,8 @@ var __webpack_exports__ = {};
|
|
|
319
328
|
headTags.unshift({
|
|
320
329
|
tag: "script",
|
|
321
330
|
attrs: {
|
|
322
|
-
src: url
|
|
331
|
+
src: url,
|
|
332
|
+
[ASSETS_RETRY_DATA_ATTRIBUTE]: 'external'
|
|
323
333
|
}
|
|
324
334
|
});
|
|
325
335
|
return {
|
|
@@ -331,30 +341,32 @@ var __webpack_exports__ = {};
|
|
|
331
341
|
stage: 'additional'
|
|
332
342
|
}, async ({ sources, compilation, environment })=>{
|
|
333
343
|
const scriptPath = getScriptPath(environment);
|
|
334
|
-
const
|
|
335
|
-
const runtimeOptions = getRuntimeOptions(
|
|
336
|
-
const code = await getRetryCode(runtimeOptions,
|
|
344
|
+
const { crossorigin, minify } = getDefaultValueFromRsbuildConfig(environment.config);
|
|
345
|
+
const runtimeOptions = getRuntimeOptions(userOptions, crossorigin);
|
|
346
|
+
const code = await getRetryCode(runtimeOptions, minify);
|
|
337
347
|
compilation.emitAsset(scriptPath, new sources.RawSource(code));
|
|
338
348
|
});
|
|
339
349
|
}
|
|
340
350
|
api.modifyBundlerChain(async (chain, { environment })=>{
|
|
341
351
|
const { config, htmlPaths } = environment;
|
|
342
352
|
if (!userOptions || 0 === Object.keys(htmlPaths).length) return;
|
|
343
|
-
const
|
|
344
|
-
const runtimeOptions = getRuntimeOptions(
|
|
353
|
+
const { crossorigin, minify } = getDefaultValueFromRsbuildConfig(config);
|
|
354
|
+
const runtimeOptions = getRuntimeOptions(userOptions, crossorigin);
|
|
345
355
|
const isRspack = 'rspack' === api.context.bundlerType;
|
|
346
356
|
chain.plugin('async-chunk-retry').use(AsyncChunkRetryPlugin, [
|
|
347
357
|
runtimeOptions,
|
|
348
358
|
isRspack,
|
|
349
|
-
|
|
359
|
+
minify
|
|
350
360
|
]);
|
|
351
361
|
});
|
|
352
362
|
}
|
|
353
363
|
});
|
|
354
364
|
})();
|
|
365
|
+
exports.ASSETS_RETRY_DATA_ATTRIBUTE = __webpack_exports__.ASSETS_RETRY_DATA_ATTRIBUTE;
|
|
355
366
|
exports.PLUGIN_ASSETS_RETRY_NAME = __webpack_exports__.PLUGIN_ASSETS_RETRY_NAME;
|
|
356
367
|
exports.pluginAssetsRetry = __webpack_exports__.pluginAssetsRetry;
|
|
357
368
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
369
|
+
"ASSETS_RETRY_DATA_ATTRIBUTE",
|
|
358
370
|
"PLUGIN_ASSETS_RETRY_NAME",
|
|
359
371
|
"pluginAssetsRetry"
|
|
360
372
|
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { CrossOrigin as CrossOrigin_2 } from '@rsbuild/core';
|
|
2
2
|
import type { RsbuildPlugin } from '@rsbuild/core';
|
|
3
3
|
|
|
4
|
+
export declare const ASSETS_RETRY_DATA_ATTRIBUTE = "data-rsbuild-assets-retry";
|
|
5
|
+
|
|
4
6
|
declare type AssetsRetryHookContext_2 = {
|
|
5
7
|
url: string;
|
|
6
8
|
times: number;
|
|
@@ -26,7 +28,9 @@ export declare const PLUGIN_ASSETS_RETRY_NAME = "rsbuild:assets-retry";
|
|
|
26
28
|
|
|
27
29
|
export declare const pluginAssetsRetry: (userOptions?: PluginAssetsRetryOptions) => RsbuildPlugin;
|
|
28
30
|
|
|
29
|
-
export declare type PluginAssetsRetryOptions = RuntimeRetryOptions & CompileTimeRetryOptions
|
|
31
|
+
export declare type PluginAssetsRetryOptions = (RuntimeRetryOptions & CompileTimeRetryOptions) | ({
|
|
32
|
+
rules: RuntimeRetryOptions[];
|
|
33
|
+
} & CompileTimeRetryOptions);
|
|
30
34
|
|
|
31
35
|
declare type RuntimeRetryOptions = RuntimeRetryOptionsWithDefaultValue & RuntimeRetryOptionsWithoutDefaultValue;
|
|
32
36
|
|
|
@@ -78,7 +82,7 @@ declare type RuntimeRetryOptionsWithoutDefaultValue = {
|
|
|
78
82
|
/**
|
|
79
83
|
* The test function of the asset to be retried.
|
|
80
84
|
*/
|
|
81
|
-
test?: string | ((url: string) => boolean);
|
|
85
|
+
test?: string | RegExp | ((url: string) => boolean);
|
|
82
86
|
/**
|
|
83
87
|
* The callback function when the asset is failed to be retried.
|
|
84
88
|
*/
|
package/dist/index.js
CHANGED
|
@@ -225,8 +225,9 @@ class AsyncChunkRetryPlugin {
|
|
|
225
225
|
}
|
|
226
226
|
const src_dirname = node_path.dirname(fileURLToPath(import.meta.url));
|
|
227
227
|
const PLUGIN_ASSETS_RETRY_NAME = 'rsbuild:assets-retry';
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
const ASSETS_RETRY_DATA_ATTRIBUTE = 'data-rsbuild-assets-retry';
|
|
229
|
+
function getRuntimeOptions(userOptions, defaultCrossOrigin) {
|
|
230
|
+
const { inlineScript, minify, ...runtimeOptions } = userOptions;
|
|
230
231
|
const defaultOptions = {
|
|
231
232
|
max: 3,
|
|
232
233
|
type: [
|
|
@@ -235,18 +236,27 @@ function getRuntimeOptions(userOptions) {
|
|
|
235
236
|
'img'
|
|
236
237
|
],
|
|
237
238
|
domain: [],
|
|
238
|
-
crossOrigin:
|
|
239
|
+
crossOrigin: defaultCrossOrigin,
|
|
239
240
|
delay: 0,
|
|
240
241
|
addQuery: false
|
|
241
242
|
};
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
243
|
+
function normalizeOption(options) {
|
|
244
|
+
const result = {
|
|
245
|
+
...defaultOptions,
|
|
246
|
+
...options
|
|
247
|
+
};
|
|
248
|
+
if (!Array.isArray(result.type) || 0 === result.type.length) result.type = defaultOptions.type;
|
|
249
|
+
if (!Array.isArray(result.domain) || 0 === result.domain.length) result.domain = defaultOptions.domain;
|
|
250
|
+
if (Array.isArray(result.domain)) result.domain = result.domain.filter(Boolean);
|
|
251
|
+
return result;
|
|
252
|
+
}
|
|
253
|
+
if ('rules' in runtimeOptions) {
|
|
254
|
+
const result = runtimeOptions.rules.map((i)=>normalizeOption(i));
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
return [
|
|
258
|
+
normalizeOption(runtimeOptions)
|
|
259
|
+
];
|
|
250
260
|
}
|
|
251
261
|
async function getRetryCode(runtimeOptions, minify) {
|
|
252
262
|
const filename = 'initialChunkRetry';
|
|
@@ -260,27 +270,25 @@ const pluginAssetsRetry = (userOptions = {})=>({
|
|
|
260
270
|
const { inlineScript = true } = userOptions;
|
|
261
271
|
const getScriptPath = (environment)=>{
|
|
262
272
|
const distDir = environment.config.output.distPath.js;
|
|
263
|
-
return node_path.posix.join(distDir, "assets-retry.1-
|
|
273
|
+
return node_path.posix.join(distDir, "assets-retry.1-4-0.js");
|
|
264
274
|
};
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
275
|
+
const getDefaultValueFromRsbuildConfig = (config)=>{
|
|
276
|
+
var _config_output_minify;
|
|
277
|
+
const minify = 'boolean' == typeof config.output.minify ? config.output.minify : null == (_config_output_minify = config.output.minify) ? void 0 : _config_output_minify.js;
|
|
278
|
+
return {
|
|
279
|
+
crossorigin: config.html.crossorigin,
|
|
280
|
+
minify: Boolean(minify) && 'production' === config.mode
|
|
268
281
|
};
|
|
269
|
-
if (void 0 === options.crossOrigin) options.crossOrigin = config.html.crossorigin;
|
|
270
|
-
if (void 0 === options.minify) {
|
|
271
|
-
var _config_output_minify;
|
|
272
|
-
const minify = 'boolean' == typeof config.output.minify ? config.output.minify : null == (_config_output_minify = config.output.minify) ? void 0 : _config_output_minify.js;
|
|
273
|
-
options.minify = minify && 'production' === config.mode;
|
|
274
|
-
}
|
|
275
|
-
return options;
|
|
276
282
|
};
|
|
277
283
|
if (inlineScript) api.modifyHTMLTags(async ({ headTags, bodyTags }, { environment })=>{
|
|
278
|
-
const
|
|
279
|
-
const runtimeOptions = getRuntimeOptions(
|
|
280
|
-
const code = await getRetryCode(runtimeOptions,
|
|
284
|
+
const { minify, crossorigin } = getDefaultValueFromRsbuildConfig(environment.config);
|
|
285
|
+
const runtimeOptions = getRuntimeOptions(userOptions, crossorigin);
|
|
286
|
+
const code = await getRetryCode(runtimeOptions, minify);
|
|
281
287
|
headTags.unshift({
|
|
282
288
|
tag: "script",
|
|
283
|
-
attrs: {
|
|
289
|
+
attrs: {
|
|
290
|
+
[ASSETS_RETRY_DATA_ATTRIBUTE]: 'inline'
|
|
291
|
+
},
|
|
284
292
|
children: code
|
|
285
293
|
});
|
|
286
294
|
return {
|
|
@@ -295,7 +303,8 @@ const pluginAssetsRetry = (userOptions = {})=>({
|
|
|
295
303
|
headTags.unshift({
|
|
296
304
|
tag: "script",
|
|
297
305
|
attrs: {
|
|
298
|
-
src: url
|
|
306
|
+
src: url,
|
|
307
|
+
[ASSETS_RETRY_DATA_ATTRIBUTE]: 'external'
|
|
299
308
|
}
|
|
300
309
|
});
|
|
301
310
|
return {
|
|
@@ -307,24 +316,24 @@ const pluginAssetsRetry = (userOptions = {})=>({
|
|
|
307
316
|
stage: 'additional'
|
|
308
317
|
}, async ({ sources, compilation, environment })=>{
|
|
309
318
|
const scriptPath = getScriptPath(environment);
|
|
310
|
-
const
|
|
311
|
-
const runtimeOptions = getRuntimeOptions(
|
|
312
|
-
const code = await getRetryCode(runtimeOptions,
|
|
319
|
+
const { crossorigin, minify } = getDefaultValueFromRsbuildConfig(environment.config);
|
|
320
|
+
const runtimeOptions = getRuntimeOptions(userOptions, crossorigin);
|
|
321
|
+
const code = await getRetryCode(runtimeOptions, minify);
|
|
313
322
|
compilation.emitAsset(scriptPath, new sources.RawSource(code));
|
|
314
323
|
});
|
|
315
324
|
}
|
|
316
325
|
api.modifyBundlerChain(async (chain, { environment })=>{
|
|
317
326
|
const { config, htmlPaths } = environment;
|
|
318
327
|
if (!userOptions || 0 === Object.keys(htmlPaths).length) return;
|
|
319
|
-
const
|
|
320
|
-
const runtimeOptions = getRuntimeOptions(
|
|
328
|
+
const { crossorigin, minify } = getDefaultValueFromRsbuildConfig(config);
|
|
329
|
+
const runtimeOptions = getRuntimeOptions(userOptions, crossorigin);
|
|
321
330
|
const isRspack = 'rspack' === api.context.bundlerType;
|
|
322
331
|
chain.plugin('async-chunk-retry').use(AsyncChunkRetryPlugin, [
|
|
323
332
|
runtimeOptions,
|
|
324
333
|
isRspack,
|
|
325
|
-
|
|
334
|
+
minify
|
|
326
335
|
]);
|
|
327
336
|
});
|
|
328
337
|
}
|
|
329
338
|
});
|
|
330
|
-
export { PLUGIN_ASSETS_RETRY_NAME, pluginAssetsRetry };
|
|
339
|
+
export { ASSETS_RETRY_DATA_ATTRIBUTE, PLUGIN_ASSETS_RETRY_NAME, pluginAssetsRetry };
|
|
@@ -3,18 +3,17 @@
|
|
|
3
3
|
var ERROR_PREFIX = '[@rsbuild/plugin-assets-retry] ';
|
|
4
4
|
function findCurrentDomain(url, config) {
|
|
5
5
|
var domains = config.domain;
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
domain
|
|
9
|
-
break;
|
|
6
|
+
for(var i = 0; i < domains.length; i++){
|
|
7
|
+
var domain = domains[i];
|
|
8
|
+
if (-1 !== url.indexOf(domain)) return domain;
|
|
10
9
|
}
|
|
11
|
-
return
|
|
10
|
+
return window.origin;
|
|
12
11
|
}
|
|
13
12
|
function findNextDomain(url, config) {
|
|
14
13
|
var domains = config.domain;
|
|
15
14
|
var currentDomain = findCurrentDomain(url, config);
|
|
16
15
|
var index = domains.indexOf(currentDomain);
|
|
17
|
-
return domains[(index + 1) % domains.length]
|
|
16
|
+
return -1 === index ? currentDomain : domains[(index + 1) % domains.length];
|
|
18
17
|
}
|
|
19
18
|
var postfixRE = /[?#].*$/;
|
|
20
19
|
function cleanUrl(url) {
|
|
@@ -35,8 +34,32 @@
|
|
|
35
34
|
function getNextRetryUrl(currRetryUrl, domain, nextDomain, existRetryTimes, originalQuery, config) {
|
|
36
35
|
return cleanUrl(currRetryUrl.replace(domain, nextDomain)) + getUrlRetryQuery(existRetryTimes + 1, originalQuery, config);
|
|
37
36
|
}
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
function _instanceof(left, right) {
|
|
38
|
+
if (null != right && "undefined" != typeof Symbol && right[Symbol.hasInstance]) return !!right[Symbol.hasInstance](left);
|
|
39
|
+
return left instanceof right;
|
|
40
|
+
}
|
|
41
|
+
function findMatchingRule(url, type, rules) {
|
|
42
|
+
for(var i = 0; i < rules.length; i++){
|
|
43
|
+
var rule = rules[i];
|
|
44
|
+
var tester = rule.test;
|
|
45
|
+
var shouldMatch = true;
|
|
46
|
+
if (_instanceof(tester, RegExp)) shouldMatch = tester.test(url);
|
|
47
|
+
else if ('string' == typeof tester) {
|
|
48
|
+
var regexp = new RegExp(tester);
|
|
49
|
+
shouldMatch = regexp.test(url);
|
|
50
|
+
} else if ('function' == typeof tester) shouldMatch = tester(url);
|
|
51
|
+
if (rule.domain && rule.domain.length > 0) {
|
|
52
|
+
var domain = findCurrentDomain(url, rule);
|
|
53
|
+
if (!rule.domain.includes(domain)) shouldMatch = false;
|
|
54
|
+
}
|
|
55
|
+
if (rule.type && rule.type.length > 0) {
|
|
56
|
+
if (!rule.type.includes(type)) shouldMatch = false;
|
|
57
|
+
}
|
|
58
|
+
if (shouldMatch) return rule;
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
var asyncChunkRetry_rules = __RETRY_OPTIONS__;
|
|
40
63
|
var retryCollector = {};
|
|
41
64
|
var retryCssCollector = {};
|
|
42
65
|
var globalCurrRetrying = {};
|
|
@@ -52,13 +75,17 @@
|
|
|
52
75
|
var originalSrcUrl = '/' === originalPublicPath[0] && '/' !== originalPublicPath[1] ? window.origin + originalPublicPath + originalScriptFilename : originalPublicPath + originalScriptFilename;
|
|
53
76
|
var originalQuery = getQueryFromUrl(originalSrcUrl);
|
|
54
77
|
var existRetryTimes = 0;
|
|
55
|
-
var
|
|
78
|
+
var tagName = isCssAsyncChunk ? 'link' : "script";
|
|
79
|
+
var rule = findMatchingRule(originalSrcUrl, tagName, asyncChunkRetry_rules);
|
|
80
|
+
if (!rule) return null;
|
|
81
|
+
var nextDomain = findCurrentDomain(originalSrcUrl, rule);
|
|
56
82
|
return {
|
|
57
83
|
nextDomain: nextDomain,
|
|
58
|
-
nextRetryUrl: getNextRetryUrl(originalSrcUrl, nextDomain, nextDomain, existRetryTimes, originalQuery,
|
|
84
|
+
nextRetryUrl: getNextRetryUrl(originalSrcUrl, nextDomain, nextDomain, existRetryTimes, originalQuery, rule),
|
|
59
85
|
originalScriptFilename: originalScriptFilename,
|
|
60
86
|
originalSrcUrl: originalSrcUrl,
|
|
61
|
-
originalQuery: originalQuery
|
|
87
|
+
originalQuery: originalQuery,
|
|
88
|
+
rule: rule
|
|
62
89
|
};
|
|
63
90
|
}
|
|
64
91
|
function asyncChunkRetry_nextRetry(chunkId, existRetryTimes, isCssAsyncChunk) {
|
|
@@ -67,17 +94,19 @@
|
|
|
67
94
|
var nextExistRetryTimes = existRetryTimes + 1;
|
|
68
95
|
if (0 === existRetryTimes || void 0 === currRetry) {
|
|
69
96
|
nextRetry = initRetry(chunkId, isCssAsyncChunk);
|
|
97
|
+
if (!nextRetry) return null;
|
|
70
98
|
if (isCssAsyncChunk) retryCssCollector[chunkId] = [];
|
|
71
99
|
else retryCollector[chunkId] = [];
|
|
72
100
|
} else {
|
|
73
|
-
var originalScriptFilename = currRetry.originalScriptFilename, originalSrcUrl = currRetry.originalSrcUrl, originalQuery = currRetry.originalQuery;
|
|
74
|
-
var nextDomain = findNextDomain(currRetry.nextDomain,
|
|
101
|
+
var originalScriptFilename = currRetry.originalScriptFilename, originalSrcUrl = currRetry.originalSrcUrl, originalQuery = currRetry.originalQuery, rule = currRetry.rule;
|
|
102
|
+
var nextDomain = findNextDomain(currRetry.nextDomain, rule);
|
|
75
103
|
nextRetry = {
|
|
76
104
|
nextDomain: nextDomain,
|
|
77
|
-
nextRetryUrl: getNextRetryUrl(currRetry.nextRetryUrl, currRetry.nextDomain, nextDomain, existRetryTimes, originalQuery,
|
|
105
|
+
nextRetryUrl: getNextRetryUrl(currRetry.nextRetryUrl, currRetry.nextDomain, nextDomain, existRetryTimes, originalQuery, rule),
|
|
78
106
|
originalScriptFilename: originalScriptFilename,
|
|
79
107
|
originalSrcUrl: originalSrcUrl,
|
|
80
|
-
originalQuery: originalQuery
|
|
108
|
+
originalQuery: originalQuery,
|
|
109
|
+
rule: rule
|
|
81
110
|
};
|
|
82
111
|
}
|
|
83
112
|
if (isCssAsyncChunk) {
|
|
@@ -123,16 +152,19 @@
|
|
|
123
152
|
var originalScriptFilename;
|
|
124
153
|
var nextRetryUrl;
|
|
125
154
|
var nextDomain;
|
|
155
|
+
var rule;
|
|
126
156
|
var isCssAsyncChunkLoadFailed = Boolean(null == error ? void 0 : null == (_error_message = error.message) ? void 0 : _error_message.includes('CSS chunk'));
|
|
127
157
|
if (isCssAsyncChunkLoadFailed) callingCounter.cssFailedCount += 1;
|
|
128
158
|
var existRetryTimes = isCssAsyncChunkLoadFailed ? cssExistRetryTimes : jsExistRetryTimes;
|
|
129
159
|
try {
|
|
130
160
|
var retryResult = asyncChunkRetry_nextRetry(chunkId, existRetryTimes, isCssAsyncChunkLoadFailed);
|
|
161
|
+
if (!retryResult) throw error;
|
|
131
162
|
originalScriptFilename = retryResult.originalScriptFilename;
|
|
132
163
|
nextRetryUrl = retryResult.nextRetryUrl;
|
|
133
164
|
nextDomain = retryResult.nextDomain;
|
|
165
|
+
rule = retryResult.rule;
|
|
134
166
|
} catch (e) {
|
|
135
|
-
console.error(ERROR_PREFIX, 'failed to get nextRetryUrl', e);
|
|
167
|
+
if (e !== error) console.error(ERROR_PREFIX, 'failed to get nextRetryUrl', e);
|
|
136
168
|
throw error;
|
|
137
169
|
}
|
|
138
170
|
var createContext = function(times) {
|
|
@@ -145,25 +177,14 @@
|
|
|
145
177
|
};
|
|
146
178
|
};
|
|
147
179
|
var context = createContext(existRetryTimes);
|
|
148
|
-
if (existRetryTimes >=
|
|
180
|
+
if (existRetryTimes >= rule.max) {
|
|
149
181
|
var _error_message1;
|
|
150
|
-
error.message = (null == (_error_message1 = error.message) ? void 0 : _error_message1.includes('retries:')) ? error.message : "Loading chunk ".concat(chunkId, ' from "').concat(originalScriptFilename, '" failed after ').concat(
|
|
151
|
-
if ('function' == typeof
|
|
182
|
+
error.message = (null == (_error_message1 = error.message) ? void 0 : _error_message1.includes('retries:')) ? error.message : "Loading chunk ".concat(chunkId, ' from "').concat(originalScriptFilename, '" failed after ').concat(rule.max, ' retries: "').concat(error.message, '"');
|
|
183
|
+
if ('function' == typeof rule.onFail) rule.onFail(context);
|
|
152
184
|
throw error;
|
|
153
185
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if ('string' == typeof tester) {
|
|
157
|
-
var regexp = new RegExp(tester);
|
|
158
|
-
tester = function(str) {
|
|
159
|
-
return regexp.test(str);
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
if ('function' != typeof tester || !tester(nextRetryUrl)) throw error;
|
|
163
|
-
}
|
|
164
|
-
if (asyncChunkRetry_config.domain && asyncChunkRetry_config.domain.length > 0 && -1 === asyncChunkRetry_config.domain.indexOf(nextDomain)) throw error;
|
|
165
|
-
if ('function' == typeof asyncChunkRetry_config.onRetry) asyncChunkRetry_config.onRetry(context);
|
|
166
|
-
var delayTime = 'function' == typeof asyncChunkRetry_config.delay ? asyncChunkRetry_config.delay(context) : asyncChunkRetry_config.delay;
|
|
186
|
+
if ('function' == typeof rule.onRetry) rule.onRetry(context);
|
|
187
|
+
var delayTime = 'function' == typeof rule.delay ? rule.delay(context) : rule.delay;
|
|
167
188
|
var delayPromise = delayTime > 0 ? new Promise(function(resolve) {
|
|
168
189
|
return setTimeout(resolve, delayTime);
|
|
169
190
|
}) : Promise.resolve();
|
|
@@ -171,9 +192,9 @@
|
|
|
171
192
|
return ensureChunk.apply(ensureChunk, args);
|
|
172
193
|
}).then(function(result) {
|
|
173
194
|
var isLastSuccessRetry = (null == callingCounter ? void 0 : callingCounter.count) === existRetryTimesAll + 2;
|
|
174
|
-
if ('function' == typeof
|
|
195
|
+
if ('function' == typeof rule.onSuccess && isLastSuccessRetry) {
|
|
175
196
|
var context = createContext(existRetryTimes + 1);
|
|
176
|
-
|
|
197
|
+
rule.onSuccess(context);
|
|
177
198
|
}
|
|
178
199
|
return result;
|
|
179
200
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(){"use strict";var n="[@rsbuild/plugin-assets-retry] ";function r(n,r){for(var e=r.domain,t=
|
|
1
|
+
!function(){"use strict";var n="[@rsbuild/plugin-assets-retry] ";function r(n,r){for(var e=r.domain,t=0;t<e.length;t++){var i=e[t];if(-1!==n.indexOf(i))return i}return window.origin}var e=/[?#].*$/;function t(n,r,t,i,o,_){var a;return n.replace(r,t).replace(e,"")+(a=i+1,!0===_.addQuery?""!==o?"".concat(o,"&retry=").concat(a):"?retry=".concat(a):"function"==typeof _.addQuery?_.addQuery({times:a,originalQuery:o}):"")}var i=__RETRY_OPTIONS__,o={},_={},a={},l={},u=__RUNTIME_GLOBALS_ENSURE_CHUNK__,c=__RUNTIME_GLOBALS_GET_CHUNK_SCRIPT_FILENAME__,s=__RUNTIME_GLOBALS_GET_MINI_CSS_EXTRACT_FILENAME__||__RUNTIME_GLOBALS_GET_CSS_FILENAME__||function(){return null},f=__RUNTIME_GLOBALS_LOAD_SCRIPT__;function y(e){var f=Array.prototype.slice.call(arguments);f[10]||(f[10]={count:0,cssFailedCount:0});var d=f[10],S=u.apply(null,f);try{var p=c(e),R=s(e);"undefined"!=typeof window&&(p&&(window.__RB_ASYNC_CHUNKS__[p]=!0),R&&(window.__RB_ASYNC_CHUNKS__[R]=!0))}catch(r){console.error(n,"get original script or CSS filename error",r)}return d&&"number"==typeof d.count&&"number"==typeof d.cssFailedCount?(d.count+=1,S.catch(function(u){var S,p,R,m,E,U,g=d.count-1,v=d.cssFailedCount,L=!!(null==u||null==(S=u.message)?void 0:S.includes("CSS chunk"));L&&(d.cssFailedCount+=1);var N=L?v:g-v;try{var A=function(n,e,u){var f,y,d,S=u?null==(f=_[n])?void 0:f[e]:null==(y=o[n])?void 0:y[e],p=e+1;if(0===e||void 0===S){if(!(d=function(n,e){var o,_=e?s(n):c(n);if(!_)throw Error("only support cssExtract");var a=__RUNTIME_GLOBALS_PUBLIC_PATH__,l="/"===a[0]&&"/"!==a[1]?window.origin+a+_:a+_,u=(o=l.split("?")[1])?"?".concat(o.split("#")[0]):"",f=function(n,e,t){for(var i=0;i<t.length;i++){var o,_=t[i],a=_.test,l=!0;if((null!=(o=RegExp)&&"undefined"!=typeof Symbol&&o[Symbol.hasInstance]?!!o[Symbol.hasInstance](a):a instanceof o)?l=a.test(n):"string"==typeof a?l=new RegExp(a).test(n):"function"==typeof a&&(l=a(n)),_.domain&&_.domain.length>0){var u=r(n,_);_.domain.includes(u)||(l=!1)}if(_.type&&_.type.length>0&&!_.type.includes(e)&&(l=!1),l)return _}return null}(l,e?"link":"script",i);if(!f)return null;var y=r(l,f);return{nextDomain:y,nextRetryUrl:t(l,y,y,0,u,f),originalScriptFilename:_,originalSrcUrl:l,originalQuery:u,rule:f}}(n,u)))return null;u?_[n]=[]:o[n]=[]}else{var R,m,E,U,g=S.originalScriptFilename,v=S.originalSrcUrl,L=S.originalQuery,N=S.rule,A=(R=S.nextDomain,m=N.domain,E=r(R,N),-1===(U=m.indexOf(E))?E:m[(U+1)%m.length]);d={nextDomain:A,nextRetryUrl:t(S.nextRetryUrl,S.nextDomain,A,e,L,N),originalScriptFilename:g,originalSrcUrl:v,originalQuery:L,rule:N}}return u?(_[n][p]=d,l[n]=d):(o[n][p]=d,a[n]=d),d}(e,N,L);if(!A)throw u;p=A.originalScriptFilename,R=A.nextRetryUrl,m=A.nextDomain,E=A.rule}catch(r){throw r!==u&&console.error(n,"failed to get nextRetryUrl",r),u}var C=function(n){return{times:n,domain:m,url:R,tagName:L?"link":"script",isAsyncChunk:!0}},I=C(N);if(N>=E.max)throw u.message=(null==(U=u.message)?void 0:U.includes("retries:"))?u.message:"Loading chunk ".concat(e,' from "').concat(p,'" failed after ').concat(E.max,' retries: "').concat(u.message,'"'),"function"==typeof E.onFail&&E.onFail(I),u;"function"==typeof E.onRetry&&E.onRetry(I);var T="function"==typeof E.delay?E.delay(I):E.delay;return(T>0?new Promise(function(n){return setTimeout(n,T)}):Promise.resolve()).then(function(){return y.apply(y,f)}).then(function(n){var r=(null==d?void 0:d.count)===g+2;if("function"==typeof E.onSuccess&&r){var e=C(N+1);E.onSuccess(e)}return n})})):S}if("undefined"==typeof window||window.__RB_ASYNC_CHUNKS__||(window.__RB_ASYNC_CHUNKS__={}),"undefined"!=typeof __RUNTIME_GLOBALS_REQUIRE__)try{__RUNTIME_GLOBALS_ENSURE_CHUNK__=y,__RUNTIME_GLOBALS_LOAD_SCRIPT__=function(){var n=Array.prototype.slice.call(arguments),r=a[n[3]];return r&&(n[0]=r.nextRetryUrl),f.apply(null,n)},__RUNTIME_GLOBALS_RSBUILD_LOAD_STYLESHEET__=function(n,r){var e=l[r];return e&&e.nextRetryUrl||__RUNTIME_GLOBALS_PUBLIC_PATH__+n}}catch(r){console.error(n,"Register async chunk retry runtime failed",r)}}();
|
|
@@ -3,18 +3,17 @@
|
|
|
3
3
|
var ERROR_PREFIX = '[@rsbuild/plugin-assets-retry] ';
|
|
4
4
|
function findCurrentDomain(url, config) {
|
|
5
5
|
var domains = config.domain;
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
domain
|
|
9
|
-
break;
|
|
6
|
+
for(var i = 0; i < domains.length; i++){
|
|
7
|
+
var domain = domains[i];
|
|
8
|
+
if (-1 !== url.indexOf(domain)) return domain;
|
|
10
9
|
}
|
|
11
|
-
return
|
|
10
|
+
return window.origin;
|
|
12
11
|
}
|
|
13
12
|
function findNextDomain(url, config) {
|
|
14
13
|
var domains = config.domain;
|
|
15
14
|
var currentDomain = findCurrentDomain(url, config);
|
|
16
15
|
var index = domains.indexOf(currentDomain);
|
|
17
|
-
return domains[(index + 1) % domains.length]
|
|
16
|
+
return -1 === index ? currentDomain : domains[(index + 1) % domains.length];
|
|
18
17
|
}
|
|
19
18
|
var postfixRE = /[?#].*$/;
|
|
20
19
|
function cleanUrl(url) {
|
|
@@ -39,26 +38,58 @@
|
|
|
39
38
|
if (null != right && "undefined" != typeof Symbol && right[Symbol.hasInstance]) return !!right[Symbol.hasInstance](left);
|
|
40
39
|
return left instanceof right;
|
|
41
40
|
}
|
|
41
|
+
function findMatchingRule(url, type, rules) {
|
|
42
|
+
for(var i = 0; i < rules.length; i++){
|
|
43
|
+
var rule = rules[i];
|
|
44
|
+
var tester = rule.test;
|
|
45
|
+
var shouldMatch = true;
|
|
46
|
+
if (_instanceof(tester, RegExp)) shouldMatch = tester.test(url);
|
|
47
|
+
else if ('string' == typeof tester) {
|
|
48
|
+
var regexp = new RegExp(tester);
|
|
49
|
+
shouldMatch = regexp.test(url);
|
|
50
|
+
} else if ('function' == typeof tester) shouldMatch = tester(url);
|
|
51
|
+
if (rule.domain && rule.domain.length > 0) {
|
|
52
|
+
var domain = findCurrentDomain(url, rule);
|
|
53
|
+
if (!rule.domain.includes(domain)) shouldMatch = false;
|
|
54
|
+
}
|
|
55
|
+
if (rule.type && rule.type.length > 0) {
|
|
56
|
+
if (!rule.type.includes(type)) shouldMatch = false;
|
|
57
|
+
}
|
|
58
|
+
if (shouldMatch) return rule;
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
function initialChunkRetry_instanceof(left, right) {
|
|
63
|
+
if (null != right && "undefined" != typeof Symbol && right[Symbol.hasInstance]) return !!right[Symbol.hasInstance](left);
|
|
64
|
+
return left instanceof right;
|
|
65
|
+
}
|
|
42
66
|
var TAG_TYPE = {
|
|
43
67
|
link: HTMLLinkElement,
|
|
44
68
|
script: HTMLScriptElement,
|
|
45
69
|
img: HTMLImageElement
|
|
46
70
|
};
|
|
47
71
|
function getRequestUrl(element) {
|
|
48
|
-
if (
|
|
49
|
-
if (
|
|
72
|
+
if (initialChunkRetry_instanceof(element, HTMLScriptElement) || initialChunkRetry_instanceof(element, HTMLImageElement)) return element.src;
|
|
73
|
+
if (initialChunkRetry_instanceof(element, HTMLLinkElement)) return element.href;
|
|
50
74
|
return null;
|
|
51
75
|
}
|
|
52
|
-
function validateTargetInfo(
|
|
76
|
+
function validateTargetInfo(rules, e) {
|
|
53
77
|
var target = e.target;
|
|
54
78
|
var tagName = target.tagName.toLocaleLowerCase();
|
|
55
|
-
var allowTags = config.type;
|
|
56
79
|
var url = getRequestUrl(target);
|
|
57
|
-
if (!
|
|
80
|
+
if (!url) return false;
|
|
81
|
+
var ruleIndex = Number(target.dataset.rbRuleI || '-1');
|
|
82
|
+
var rule = rules[ruleIndex] || findMatchingRule(url, tagName, rules);
|
|
83
|
+
if (!rule) return false;
|
|
84
|
+
ruleIndex = rules.indexOf(rule);
|
|
85
|
+
var allowTags = rule.type;
|
|
86
|
+
if (!tagName || -1 === allowTags.indexOf(tagName) || !TAG_TYPE[tagName] || !initialChunkRetry_instanceof(target, TAG_TYPE[tagName])) return false;
|
|
58
87
|
return {
|
|
59
88
|
target: target,
|
|
60
89
|
tagName: tagName,
|
|
61
|
-
url: url
|
|
90
|
+
url: url,
|
|
91
|
+
rule: rule,
|
|
92
|
+
ruleIndex: ruleIndex
|
|
62
93
|
};
|
|
63
94
|
}
|
|
64
95
|
function createElement(origin, attributes) {
|
|
@@ -66,20 +97,22 @@
|
|
|
66
97
|
var crossOriginAttr = crossOrigin ? 'crossorigin="'.concat(crossOrigin, '"') : '';
|
|
67
98
|
var retryTimesAttr = attributes.times ? 'data-rb-retry-times="'.concat(attributes.times, '"') : '';
|
|
68
99
|
var originalQueryAttr = attributes.originalQuery ? 'data-rb-original-query="'.concat(attributes.originalQuery, '"') : '';
|
|
100
|
+
var ruleIndexAttr = attributes.ruleIndex >= 0 ? 'data-rb-rule-i="'.concat(attributes.ruleIndex, '"') : '';
|
|
69
101
|
var isAsyncAttr = attributes.isAsync ? 'data-rb-async' : '';
|
|
70
|
-
if (
|
|
102
|
+
if (initialChunkRetry_instanceof(origin, HTMLScriptElement)) {
|
|
71
103
|
var script = document.createElement("script");
|
|
72
104
|
script.src = attributes.url;
|
|
73
105
|
if (crossOrigin) script.crossOrigin = crossOrigin;
|
|
74
106
|
if (attributes.times) script.dataset.rbRetryTimes = String(attributes.times);
|
|
75
107
|
if (attributes.isAsync) script.dataset.rbAsync = '';
|
|
76
108
|
if (void 0 !== attributes.originalQuery) script.dataset.rbOriginalQuery = attributes.originalQuery;
|
|
109
|
+
if (attributes.ruleIndex >= 0) script.dataset.rbRuleI = String(attributes.ruleIndex);
|
|
77
110
|
return {
|
|
78
111
|
element: script,
|
|
79
|
-
str: '<script src="'.concat(attributes.url, '" ').concat(crossOriginAttr, " ").concat(retryTimesAttr, " ").concat(isAsyncAttr, " ").concat(originalQueryAttr, ">") + "<\/script>"
|
|
112
|
+
str: '<script src="'.concat(attributes.url, '" ').concat(crossOriginAttr, " ").concat(retryTimesAttr, " ").concat(isAsyncAttr, " ").concat(ruleIndexAttr, " ").concat(originalQueryAttr, ">") + "<\/script>"
|
|
80
113
|
};
|
|
81
114
|
}
|
|
82
|
-
if (
|
|
115
|
+
if (initialChunkRetry_instanceof(origin, HTMLLinkElement)) {
|
|
83
116
|
var link = document.createElement('link');
|
|
84
117
|
link.rel = origin.rel || 'stylesheet';
|
|
85
118
|
if (origin.as) link.as = origin.as;
|
|
@@ -89,42 +122,31 @@
|
|
|
89
122
|
if (void 0 !== attributes.originalQuery) link.dataset.rbOriginalQuery = attributes.originalQuery;
|
|
90
123
|
return {
|
|
91
124
|
element: link,
|
|
92
|
-
str: '<link rel="'.concat(link.rel, '" href="').concat(attributes.url, '" ').concat(crossOriginAttr, " ").concat(retryTimesAttr, " ").concat(link.as ? 'as="'.concat(link.as, '"') : '', " ").concat(originalQueryAttr, "></link>")
|
|
125
|
+
str: '<link rel="'.concat(link.rel, '" href="').concat(attributes.url, '" ').concat(crossOriginAttr, " ").concat(retryTimesAttr, " ").concat(link.as ? 'as="'.concat(link.as, '"') : '', " ").concat(ruleIndexAttr, " ").concat(originalQueryAttr, "></link>")
|
|
93
126
|
};
|
|
94
127
|
}
|
|
95
128
|
}
|
|
96
129
|
function reloadElementResource(origin, fresh, attributes) {
|
|
97
|
-
if (
|
|
130
|
+
if (initialChunkRetry_instanceof(origin, HTMLScriptElement)) if (attributes.isAsync) document.body.appendChild(fresh.element);
|
|
98
131
|
else console.warn(ERROR_PREFIX, "load sync script failed, for security only async/defer script can be retried", origin);
|
|
99
|
-
if (
|
|
100
|
-
if (
|
|
132
|
+
if (initialChunkRetry_instanceof(origin, HTMLLinkElement)) document.getElementsByTagName('head')[0].appendChild(fresh.element);
|
|
133
|
+
if (initialChunkRetry_instanceof(origin, HTMLImageElement)) {
|
|
101
134
|
origin.src = attributes.url;
|
|
102
135
|
origin.dataset.rbRetryTimes = String(attributes.times);
|
|
103
136
|
origin.dataset.rbOriginalQuery = String(attributes.originalQuery);
|
|
104
137
|
}
|
|
105
138
|
}
|
|
106
|
-
function retry(
|
|
107
|
-
var targetInfo = validateTargetInfo(
|
|
139
|
+
function retry(rules, e) {
|
|
140
|
+
var targetInfo = validateTargetInfo(rules, e);
|
|
108
141
|
if (false === targetInfo) return;
|
|
109
|
-
var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url;
|
|
142
|
+
var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url, rule = targetInfo.rule, ruleIndex = targetInfo.ruleIndex;
|
|
110
143
|
if ('undefined' != typeof window && Object.keys(window.__RB_ASYNC_CHUNKS__ || {}).some(function(chunkName) {
|
|
111
144
|
return -1 !== url.indexOf(chunkName);
|
|
112
145
|
})) return;
|
|
113
|
-
var
|
|
114
|
-
if (tester) {
|
|
115
|
-
if ('string' == typeof tester) {
|
|
116
|
-
var regexp = new RegExp(tester);
|
|
117
|
-
tester = function(str) {
|
|
118
|
-
return regexp.test(str);
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
if ('function' != typeof tester || !tester(url)) return;
|
|
122
|
-
}
|
|
123
|
-
var domain = findCurrentDomain(url, config);
|
|
124
|
-
if (config.domain && config.domain.length > 0 && -1 === config.domain.indexOf(domain)) return;
|
|
146
|
+
var domain = findCurrentDomain(url, rule);
|
|
125
147
|
var existRetryTimes = Number(target.dataset.rbRetryTimes) || 0;
|
|
126
|
-
if (existRetryTimes ===
|
|
127
|
-
if ('function' == typeof
|
|
148
|
+
if (existRetryTimes === rule.max) {
|
|
149
|
+
if ('function' == typeof rule.onFail) {
|
|
128
150
|
var context = {
|
|
129
151
|
times: existRetryTimes,
|
|
130
152
|
domain: domain,
|
|
@@ -132,20 +154,21 @@
|
|
|
132
154
|
tagName: tagName,
|
|
133
155
|
isAsyncChunk: false
|
|
134
156
|
};
|
|
135
|
-
|
|
157
|
+
rule.onFail(context);
|
|
136
158
|
}
|
|
137
159
|
return;
|
|
138
160
|
}
|
|
139
|
-
var nextDomain = findNextDomain(domain,
|
|
161
|
+
var nextDomain = findNextDomain(domain, rule);
|
|
140
162
|
var _target_dataset_rbOriginalQuery;
|
|
141
163
|
var originalQuery = null != (_target_dataset_rbOriginalQuery = target.dataset.rbOriginalQuery) ? _target_dataset_rbOriginalQuery : getQueryFromUrl(url);
|
|
142
164
|
var isAsync = Boolean(target.dataset.rbAsync) || target.async || target.defer;
|
|
143
165
|
var attributes = {
|
|
144
|
-
url: getNextRetryUrl(url, domain, nextDomain, existRetryTimes, originalQuery,
|
|
166
|
+
url: getNextRetryUrl(url, domain, nextDomain, existRetryTimes, originalQuery, rule),
|
|
145
167
|
times: existRetryTimes + 1,
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
168
|
+
originalQuery: originalQuery,
|
|
169
|
+
ruleIndex: ruleIndex,
|
|
170
|
+
crossOrigin: rule.crossOrigin,
|
|
171
|
+
isAsync: isAsync
|
|
149
172
|
};
|
|
150
173
|
var element = createElement(target, attributes);
|
|
151
174
|
var context1 = {
|
|
@@ -155,21 +178,21 @@
|
|
|
155
178
|
tagName: tagName,
|
|
156
179
|
isAsyncChunk: false
|
|
157
180
|
};
|
|
158
|
-
if ('function' == typeof
|
|
159
|
-
var delayValue = 'function' == typeof
|
|
181
|
+
if ('function' == typeof rule.onRetry) rule.onRetry(context1);
|
|
182
|
+
var delayValue = 'function' == typeof rule.delay ? rule.delay(context1) : rule.delay;
|
|
160
183
|
if (delayValue > 0) setTimeout(function() {
|
|
161
184
|
reloadElementResource(target, element, attributes);
|
|
162
185
|
}, delayValue);
|
|
163
186
|
else reloadElementResource(target, element, attributes);
|
|
164
187
|
}
|
|
165
|
-
function load(
|
|
166
|
-
var targetInfo = validateTargetInfo(
|
|
188
|
+
function load(rules, e) {
|
|
189
|
+
var targetInfo = validateTargetInfo(rules, e);
|
|
167
190
|
if (false === targetInfo) return;
|
|
168
|
-
var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url;
|
|
169
|
-
var domain = findCurrentDomain(url,
|
|
191
|
+
var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url, rule = targetInfo.rule;
|
|
192
|
+
var domain = findCurrentDomain(url, rule);
|
|
170
193
|
var retryTimes = Number(target.dataset.rbRetryTimes) || 0;
|
|
171
194
|
if (0 === retryTimes) return;
|
|
172
|
-
if ('function' == typeof
|
|
195
|
+
if ('function' == typeof rule.onSuccess) {
|
|
173
196
|
var context = {
|
|
174
197
|
times: retryTimes,
|
|
175
198
|
domain: domain,
|
|
@@ -177,7 +200,7 @@
|
|
|
177
200
|
tagName: tagName,
|
|
178
201
|
isAsyncChunk: false
|
|
179
202
|
};
|
|
180
|
-
|
|
203
|
+
rule.onSuccess(context);
|
|
181
204
|
}
|
|
182
205
|
}
|
|
183
206
|
function registerInitialChunkRetry() {
|
|
@@ -186,14 +209,14 @@
|
|
|
186
209
|
var config = __RETRY_OPTIONS__;
|
|
187
210
|
if ('undefined' != typeof window && void 0 !== window.document) {
|
|
188
211
|
document.addEventListener('error', function(e) {
|
|
189
|
-
if (e &&
|
|
212
|
+
if (e && initialChunkRetry_instanceof(e.target, Element)) try {
|
|
190
213
|
retry(config, e);
|
|
191
214
|
} catch (err) {
|
|
192
215
|
console.error('retry error captured', err);
|
|
193
216
|
}
|
|
194
217
|
}, true);
|
|
195
218
|
document.addEventListener('load', function(e) {
|
|
196
|
-
if (e &&
|
|
219
|
+
if (e && initialChunkRetry_instanceof(e.target, Element)) try {
|
|
197
220
|
load(config, e);
|
|
198
221
|
} catch (err) {
|
|
199
222
|
console.error('load error captured', err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(){"use strict";function e(e,
|
|
1
|
+
!function(){"use strict";function e(e,n){for(var t=n.domain,r=0;r<t.length;r++){var a=t[r];if(-1!==e.indexOf(a))return a}return window.origin}var n=/[?#].*$/;function t(e,n){return null!=n&&"undefined"!=typeof Symbol&&n[Symbol.hasInstance]?!!n[Symbol.hasInstance](e):e instanceof n}var r={link:HTMLLinkElement,script:HTMLScriptElement,img:HTMLImageElement};function a(n,a){var i=a.target,o=i.tagName.toLocaleLowerCase(),c=t(i,HTMLScriptElement)||t(i,HTMLImageElement)?i.src:t(i,HTMLLinkElement)?i.href:null;if(!c)return!1;var s=Number(i.dataset.rbRuleI||"-1"),l=n[s]||function(n,t,r){for(var a=0;a<r.length;a++){var i,o=r[a],c=o.test,s=!0;if((null!=(i=RegExp)&&"undefined"!=typeof Symbol&&i[Symbol.hasInstance]?!!i[Symbol.hasInstance](c):c instanceof i)?s=c.test(n):"string"==typeof c?s=new RegExp(c).test(n):"function"==typeof c&&(s=c(n)),o.domain&&o.domain.length>0){var l=e(n,o);o.domain.includes(l)||(s=!1)}if(o.type&&o.type.length>0&&!o.type.includes(t)&&(s=!1),s)return o}return null}(c,o,n);if(!l)return!1;s=n.indexOf(l);var u=l.type;return!!o&&-1!==u.indexOf(o)&&!!r[o]&&!!t(i,r[o])&&{target:i,tagName:o,url:c,rule:l,ruleIndex:s}}function i(e,n,r){t(e,HTMLScriptElement)&&(r.isAsync?document.body.appendChild(n.element):console.warn("[@rsbuild/plugin-assets-retry] ","load sync script failed, for security only async/defer script can be retried",e)),t(e,HTMLLinkElement)&&document.getElementsByTagName("head")[0].appendChild(n.element),t(e,HTMLImageElement)&&(e.src=r.url,e.dataset.rbRetryTimes=r.times+"",e.dataset.rbOriginalQuery=r.originalQuery+"")}"undefined"==typeof window||window.__RB_ASYNC_CHUNKS__||(window.__RB_ASYNC_CHUNKS__={});try{var o=__RETRY_OPTIONS__;"undefined"!=typeof window&&void 0!==window.document&&(document.addEventListener("error",function(r){if(r&&t(r.target,Element))try{!function(r,o){var c,s=a(r,o);if(!1!==s){var l=s.target,u=s.tagName,d=s.url,m=s.rule,y=s.ruleIndex;if(!("undefined"!=typeof window&&Object.keys(window.__RB_ASYNC_CHUNKS__||{}).some(function(e){return -1!==d.indexOf(e)}))){var f,g,p,b,v,_=e(d,m),h=Number(l.dataset.rbRetryTimes)||0;if(h===m.max){"function"==typeof m.onFail&&m.onFail({times:h,domain:_,url:d,tagName:u,isAsyncChunk:!1});return}var E=(g=m.domain,p=e(_,m),-1===(b=g.indexOf(p))?p:g[(b+1)%g.length]),T=null!=(c=l.dataset.rbOriginalQuery)?c:(v=d.split("?")[1])?"?".concat(v.split("#")[0]):"",w=!!l.dataset.rbAsync||l.async||l.defer,L={url:d.replace(_,E).replace(n,"")+(f=h+1,!0===m.addQuery?""!==T?"".concat(T,"&retry=").concat(f):"?retry=".concat(f):"function"==typeof m.addQuery?m.addQuery({times:f,originalQuery:T}):""),times:h+1,originalQuery:T,ruleIndex:y,crossOrigin:m.crossOrigin,isAsync:w},S=function(e,n){var r=!0===n.crossOrigin?"anonymous":n.crossOrigin,a=r?'crossorigin="'.concat(r,'"'):"",i=n.times?'data-rb-retry-times="'.concat(n.times,'"'):"",o=n.originalQuery?'data-rb-original-query="'.concat(n.originalQuery,'"'):"",c=n.ruleIndex>=0?'data-rb-rule-i="'.concat(n.ruleIndex,'"'):"",s=n.isAsync?"data-rb-async":"";if(t(e,HTMLScriptElement)){var l=document.createElement("script");return l.src=n.url,r&&(l.crossOrigin=r),n.times&&(l.dataset.rbRetryTimes=n.times+""),n.isAsync&&(l.dataset.rbAsync=""),void 0!==n.originalQuery&&(l.dataset.rbOriginalQuery=n.originalQuery),n.ruleIndex>=0&&(l.dataset.rbRuleI=n.ruleIndex+""),{element:l,str:'<script src="'.concat(n.url,'" ').concat(a," ").concat(i," ").concat(s," ").concat(c," ").concat(o,">")+"<\/script>"}}if(t(e,HTMLLinkElement)){var u=document.createElement("link");return u.rel=e.rel||"stylesheet",e.as&&(u.as=e.as),u.href=n.url,r&&(u.crossOrigin=r),n.times&&(u.dataset.rbRetryTimes=n.times+""),void 0!==n.originalQuery&&(u.dataset.rbOriginalQuery=n.originalQuery),{element:u,str:'<link rel="'.concat(u.rel,'" href="').concat(n.url,'" ').concat(a," ").concat(i," ").concat(u.as?'as="'.concat(u.as,'"'):""," ").concat(c," ").concat(o,"></link>")}}}(l,L),N={times:h,domain:_,url:d,tagName:u,isAsyncChunk:!1};"function"==typeof m.onRetry&&m.onRetry(N);var O="function"==typeof m.delay?m.delay(N):m.delay;O>0?setTimeout(function(){i(l,S,L)},O):i(l,S,L)}}}(o,r)}catch(e){console.error("retry error captured",e)}},!0),document.addEventListener("load",function(n){if(n&&t(n.target,Element))try{!function(n,t){var r=a(n,t);if(!1!==r){var i=r.target,o=r.tagName,c=r.url,s=r.rule,l=e(c,s),u=Number(i.dataset.rbRetryTimes)||0;0!==u&&"function"==typeof s.onSuccess&&s.onSuccess({times:u,domain:l,url:c,tagName:o,isAsyncChunk:!1})}}(o,n)}catch(e){console.error("load error captured",e)}},!0))}catch(e){console.error("monitor error captured",e)}}();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rsbuild/plugin-assets-retry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"repository": "https://github.com/rspack-contrib/rsbuild-plugin-assets-retry",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -30,16 +30,16 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@microsoft/api-extractor": "^7.52.8",
|
|
32
32
|
"@biomejs/biome": "^1.9.4",
|
|
33
|
-
"@playwright/test": "^1.53.
|
|
34
|
-
"@rsbuild/core": "^1.
|
|
33
|
+
"@playwright/test": "^1.53.2",
|
|
34
|
+
"@rsbuild/core": "^1.4.2",
|
|
35
35
|
"@rsbuild/plugin-react": "^1.3.2",
|
|
36
|
-
"@rslib/core": "^0.10.
|
|
37
|
-
"@swc/core": "^1.12.
|
|
38
|
-
"@types/node": "^22.15.
|
|
36
|
+
"@rslib/core": "^0.10.4",
|
|
37
|
+
"@swc/core": "^1.12.7",
|
|
38
|
+
"@types/node": "^22.15.34",
|
|
39
39
|
"@types/react": "^19.1.8",
|
|
40
40
|
"@types/react-dom": "^19.1.6",
|
|
41
41
|
"@types/serialize-javascript": "^5.0.4",
|
|
42
|
-
"playwright": "^1.53.
|
|
42
|
+
"playwright": "^1.53.2",
|
|
43
43
|
"react": "^19.1.0",
|
|
44
44
|
"react-dom": "^19.1.0",
|
|
45
45
|
"serialize-javascript": "^6.0.2",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"optional": true
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
|
-
"packageManager": "pnpm@10.12.
|
|
57
|
+
"packageManager": "pnpm@10.12.4",
|
|
58
58
|
"publishConfig": {
|
|
59
59
|
"access": "public",
|
|
60
60
|
"registry": "https://registry.npmjs.org/"
|