@rsbuild/plugin-assets-retry 1.2.3 → 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 +137 -23
- package/README.zh-CN.md +137 -23
- package/dist/index.cjs +59 -56
- package/dist/index.d.ts +100 -5
- package/dist/index.js +57 -57
- package/dist/runtime/asyncChunkRetry.js +189 -222
- package/dist/runtime/asyncChunkRetry.min.js +1 -1
- package/dist/runtime/initialChunkRetry.js +205 -267
- package/dist/runtime/initialChunkRetry.min.js +1 -1
- package/package.json +9 -8
- package/dist/AsyncChunkRetryPlugin.d.ts +0 -15
- package/dist/runtime/asyncChunkRetry.d.ts +0 -19
- package/dist/runtime/initialChunkRetry.d.ts +0 -5
- package/dist/types.d.ts +0 -72
|
@@ -1,293 +1,231 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
(function() {
|
|
2
|
+
"use strict";
|
|
3
|
+
var ERROR_PREFIX = '[@rsbuild/plugin-assets-retry] ';
|
|
4
|
+
function findCurrentDomain(url, config) {
|
|
5
|
+
var domains = config.domain;
|
|
6
|
+
for(var i = 0; i < domains.length; i++){
|
|
7
|
+
var domain = domains[i];
|
|
8
|
+
if (-1 !== url.indexOf(domain)) return domain;
|
|
9
|
+
}
|
|
10
|
+
return window.origin;
|
|
11
|
+
}
|
|
12
|
+
function findNextDomain(url, config) {
|
|
13
|
+
var domains = config.domain;
|
|
14
|
+
var currentDomain = findCurrentDomain(url, config);
|
|
15
|
+
var index = domains.indexOf(currentDomain);
|
|
16
|
+
return -1 === index ? currentDomain : domains[(index + 1) % domains.length];
|
|
17
|
+
}
|
|
18
|
+
var postfixRE = /[?#].*$/;
|
|
19
|
+
function cleanUrl(url) {
|
|
20
|
+
return url.replace(postfixRE, '');
|
|
21
|
+
}
|
|
22
|
+
function getQueryFromUrl(url) {
|
|
23
|
+
var parts = url.split('?')[1];
|
|
24
|
+
return parts ? "?".concat(parts.split('#')[0]) : '';
|
|
25
|
+
}
|
|
26
|
+
function getUrlRetryQuery(existRetryTimes, originalQuery, config) {
|
|
27
|
+
if (true === config.addQuery) return '' !== originalQuery ? "".concat(originalQuery, "&retry=").concat(existRetryTimes) : "?retry=".concat(existRetryTimes);
|
|
28
|
+
if ('function' == typeof config.addQuery) return config.addQuery({
|
|
29
|
+
times: existRetryTimes,
|
|
30
|
+
originalQuery: originalQuery
|
|
31
|
+
});
|
|
32
|
+
return '';
|
|
7
33
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
link: HTMLLinkElement,
|
|
11
|
-
script: HTMLScriptElement,
|
|
12
|
-
img: HTMLImageElement
|
|
13
|
-
};
|
|
14
|
-
// this function is the same as async chunk retry
|
|
15
|
-
function findCurrentDomain(url, domains) {
|
|
16
|
-
var domain = '';
|
|
17
|
-
for(var i = 0; i < domains.length; i++){
|
|
18
|
-
if (url.indexOf(domains[i]) !== -1) {
|
|
19
|
-
domain = domains[i];
|
|
20
|
-
break;
|
|
21
|
-
}
|
|
34
|
+
function getNextRetryUrl(currRetryUrl, domain, nextDomain, existRetryTimes, originalQuery, config) {
|
|
35
|
+
return cleanUrl(currRetryUrl.replace(domain, nextDomain)) + getUrlRetryQuery(existRetryTimes + 1, originalQuery, config);
|
|
22
36
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
function findNextDomain(url, domains) {
|
|
27
|
-
var currentDomain = findCurrentDomain(url, domains);
|
|
28
|
-
var index = domains.indexOf(currentDomain);
|
|
29
|
-
return domains[(index + 1) % domains.length] || url;
|
|
30
|
-
}
|
|
31
|
-
function getRequestUrl(element) {
|
|
32
|
-
if (_instanceof(element, HTMLScriptElement) || _instanceof(element, HTMLImageElement)) {
|
|
33
|
-
var _element_getAttribute;
|
|
34
|
-
// For <script src="" /> or <img src="" />
|
|
35
|
-
// element.getAttribute('src') === '' but element.src === baseURI
|
|
36
|
-
if (!((_element_getAttribute = element.getAttribute('src')) === null || _element_getAttribute === void 0 ? void 0 : _element_getAttribute.trim())) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
return element.src;
|
|
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
40
|
}
|
|
41
|
-
|
|
42
|
-
var
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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;
|
|
46
59
|
}
|
|
47
|
-
return
|
|
60
|
+
return null;
|
|
48
61
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
var target = e.target;
|
|
53
|
-
var tagName = target.tagName.toLocaleLowerCase();
|
|
54
|
-
var allowTags = config.type;
|
|
55
|
-
var url = getRequestUrl(target);
|
|
56
|
-
if (!tagName || allowTags.indexOf(tagName) === -1 || !TAG_TYPE[tagName] || !_instanceof(target, TAG_TYPE[tagName]) || !url) {
|
|
57
|
-
return false;
|
|
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;
|
|
58
65
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
var TAG_TYPE = {
|
|
67
|
+
link: HTMLLinkElement,
|
|
68
|
+
script: HTMLScriptElement,
|
|
69
|
+
img: HTMLImageElement
|
|
63
70
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
function
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
var script = document.createElement('script');
|
|
81
|
-
script.src = attributes.url;
|
|
82
|
-
if (crossOrigin) {
|
|
83
|
-
script.crossOrigin = crossOrigin;
|
|
84
|
-
}
|
|
85
|
-
if (attributes.times) {
|
|
86
|
-
script.dataset.rbRetryTimes = String(attributes.times);
|
|
87
|
-
}
|
|
88
|
-
if (attributes.isAsync) {
|
|
89
|
-
script.dataset.rbAsync = '';
|
|
90
|
-
}
|
|
91
|
-
if (attributes.originalQuery !== undefined) {
|
|
92
|
-
script.dataset.rbOriginalQuery = attributes.originalQuery;
|
|
93
|
-
}
|
|
71
|
+
function getRequestUrl(element) {
|
|
72
|
+
if (initialChunkRetry_instanceof(element, HTMLScriptElement) || initialChunkRetry_instanceof(element, HTMLImageElement)) return element.src;
|
|
73
|
+
if (initialChunkRetry_instanceof(element, HTMLLinkElement)) return element.href;
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
function validateTargetInfo(rules, e) {
|
|
77
|
+
var target = e.target;
|
|
78
|
+
var tagName = target.tagName.toLocaleLowerCase();
|
|
79
|
+
var url = getRequestUrl(target);
|
|
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;
|
|
94
87
|
return {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (_instanceof(origin, HTMLLinkElement)) {
|
|
101
|
-
var link = document.createElement('link');
|
|
102
|
-
link.rel = origin.rel || 'stylesheet';
|
|
103
|
-
if (origin.as) {
|
|
104
|
-
link.as = origin.as;
|
|
105
|
-
}
|
|
106
|
-
link.href = attributes.url;
|
|
107
|
-
if (crossOrigin) {
|
|
108
|
-
link.crossOrigin = crossOrigin;
|
|
109
|
-
}
|
|
110
|
-
if (attributes.times) {
|
|
111
|
-
link.dataset.rbRetryTimes = String(attributes.times);
|
|
112
|
-
}
|
|
113
|
-
if (attributes.originalQuery !== undefined) {
|
|
114
|
-
link.dataset.rbOriginalQuery = attributes.originalQuery;
|
|
115
|
-
}
|
|
116
|
-
return {
|
|
117
|
-
element: link,
|
|
118
|
-
str: '<link rel="'.concat(link.rel, '" href="').concat(attributes.url, '" ').concat(crossOriginAttr, " ").concat(retryTimesAttr, " ").concat(link.as ? 'as="'.concat(link.as, '"') : '', " ").concat(originalQueryAttr, "></link>")
|
|
88
|
+
target: target,
|
|
89
|
+
tagName: tagName,
|
|
90
|
+
url: url,
|
|
91
|
+
rule: rule,
|
|
92
|
+
ruleIndex: ruleIndex
|
|
119
93
|
};
|
|
120
94
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
95
|
+
function createElement(origin, attributes) {
|
|
96
|
+
var crossOrigin = true === attributes.crossOrigin ? 'anonymous' : attributes.crossOrigin;
|
|
97
|
+
var crossOriginAttr = crossOrigin ? 'crossorigin="'.concat(crossOrigin, '"') : '';
|
|
98
|
+
var retryTimesAttr = attributes.times ? 'data-rb-retry-times="'.concat(attributes.times, '"') : '';
|
|
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, '"') : '';
|
|
101
|
+
var isAsyncAttr = attributes.isAsync ? 'data-rb-async' : '';
|
|
102
|
+
if (initialChunkRetry_instanceof(origin, HTMLScriptElement)) {
|
|
103
|
+
var script = document.createElement("script");
|
|
104
|
+
script.src = attributes.url;
|
|
105
|
+
if (crossOrigin) script.crossOrigin = crossOrigin;
|
|
106
|
+
if (attributes.times) script.dataset.rbRetryTimes = String(attributes.times);
|
|
107
|
+
if (attributes.isAsync) script.dataset.rbAsync = '';
|
|
108
|
+
if (void 0 !== attributes.originalQuery) script.dataset.rbOriginalQuery = attributes.originalQuery;
|
|
109
|
+
if (attributes.ruleIndex >= 0) script.dataset.rbRuleI = String(attributes.ruleIndex);
|
|
110
|
+
return {
|
|
111
|
+
element: script,
|
|
112
|
+
str: '<script src="'.concat(attributes.url, '" ').concat(crossOriginAttr, " ").concat(retryTimesAttr, " ").concat(isAsyncAttr, " ").concat(ruleIndexAttr, " ").concat(originalQueryAttr, ">") + "<\/script>"
|
|
113
|
+
};
|
|
128
114
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
var targetInfo = validateTargetInfo(config, e);
|
|
141
|
-
if (targetInfo === false) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url;
|
|
145
|
-
// If the requested failed chunk is async chunk,skip it, because async chunk will be retried by asyncChunkRetry runtime
|
|
146
|
-
if (typeof window !== 'undefined' && Object.keys(window.__RB_ASYNC_CHUNKS__ || {}).some(function(chunkName) {
|
|
147
|
-
return url.indexOf(chunkName) !== -1;
|
|
148
|
-
})) {
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
// Filter by config.test and config.domain
|
|
152
|
-
var tester = config.test;
|
|
153
|
-
if (tester) {
|
|
154
|
-
if (typeof tester === 'string') {
|
|
155
|
-
var regexp = new RegExp(tester);
|
|
156
|
-
tester = function(str) {
|
|
157
|
-
return regexp.test(str);
|
|
115
|
+
if (initialChunkRetry_instanceof(origin, HTMLLinkElement)) {
|
|
116
|
+
var link = document.createElement('link');
|
|
117
|
+
link.rel = origin.rel || 'stylesheet';
|
|
118
|
+
if (origin.as) link.as = origin.as;
|
|
119
|
+
link.href = attributes.url;
|
|
120
|
+
if (crossOrigin) link.crossOrigin = crossOrigin;
|
|
121
|
+
if (attributes.times) link.dataset.rbRetryTimes = String(attributes.times);
|
|
122
|
+
if (void 0 !== attributes.originalQuery) link.dataset.rbOriginalQuery = attributes.originalQuery;
|
|
123
|
+
return {
|
|
124
|
+
element: 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>")
|
|
158
126
|
};
|
|
159
127
|
}
|
|
160
|
-
|
|
128
|
+
}
|
|
129
|
+
function reloadElementResource(origin, fresh, attributes) {
|
|
130
|
+
if (initialChunkRetry_instanceof(origin, HTMLScriptElement)) if (attributes.isAsync) document.body.appendChild(fresh.element);
|
|
131
|
+
else console.warn(ERROR_PREFIX, "load sync script failed, for security only async/defer script can be retried", origin);
|
|
132
|
+
if (initialChunkRetry_instanceof(origin, HTMLLinkElement)) document.getElementsByTagName('head')[0].appendChild(fresh.element);
|
|
133
|
+
if (initialChunkRetry_instanceof(origin, HTMLImageElement)) {
|
|
134
|
+
origin.src = attributes.url;
|
|
135
|
+
origin.dataset.rbRetryTimes = String(attributes.times);
|
|
136
|
+
origin.dataset.rbOriginalQuery = String(attributes.originalQuery);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function retry(rules, e) {
|
|
140
|
+
var targetInfo = validateTargetInfo(rules, e);
|
|
141
|
+
if (false === targetInfo) return;
|
|
142
|
+
var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url, rule = targetInfo.rule, ruleIndex = targetInfo.ruleIndex;
|
|
143
|
+
if ('undefined' != typeof window && Object.keys(window.__RB_ASYNC_CHUNKS__ || {}).some(function(chunkName) {
|
|
144
|
+
return -1 !== url.indexOf(chunkName);
|
|
145
|
+
})) return;
|
|
146
|
+
var domain = findCurrentDomain(url, rule);
|
|
147
|
+
var existRetryTimes = Number(target.dataset.rbRetryTimes) || 0;
|
|
148
|
+
if (existRetryTimes === rule.max) {
|
|
149
|
+
if ('function' == typeof rule.onFail) {
|
|
150
|
+
var context = {
|
|
151
|
+
times: existRetryTimes,
|
|
152
|
+
domain: domain,
|
|
153
|
+
url: url,
|
|
154
|
+
tagName: tagName,
|
|
155
|
+
isAsyncChunk: false
|
|
156
|
+
};
|
|
157
|
+
rule.onFail(context);
|
|
158
|
+
}
|
|
161
159
|
return;
|
|
162
160
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
161
|
+
var nextDomain = findNextDomain(domain, rule);
|
|
162
|
+
var _target_dataset_rbOriginalQuery;
|
|
163
|
+
var originalQuery = null != (_target_dataset_rbOriginalQuery = target.dataset.rbOriginalQuery) ? _target_dataset_rbOriginalQuery : getQueryFromUrl(url);
|
|
164
|
+
var isAsync = Boolean(target.dataset.rbAsync) || target.async || target.defer;
|
|
165
|
+
var attributes = {
|
|
166
|
+
url: getNextRetryUrl(url, domain, nextDomain, existRetryTimes, originalQuery, rule),
|
|
167
|
+
times: existRetryTimes + 1,
|
|
168
|
+
originalQuery: originalQuery,
|
|
169
|
+
ruleIndex: ruleIndex,
|
|
170
|
+
crossOrigin: rule.crossOrigin,
|
|
171
|
+
isAsync: isAsync
|
|
172
|
+
};
|
|
173
|
+
var element = createElement(target, attributes);
|
|
174
|
+
var context1 = {
|
|
175
|
+
times: existRetryTimes,
|
|
176
|
+
domain: domain,
|
|
177
|
+
url: url,
|
|
178
|
+
tagName: tagName,
|
|
179
|
+
isAsyncChunk: false
|
|
180
|
+
};
|
|
181
|
+
if ('function' == typeof rule.onRetry) rule.onRetry(context1);
|
|
182
|
+
var delayValue = 'function' == typeof rule.delay ? rule.delay(context1) : rule.delay;
|
|
183
|
+
if (delayValue > 0) setTimeout(function() {
|
|
184
|
+
reloadElementResource(target, element, attributes);
|
|
185
|
+
}, delayValue);
|
|
186
|
+
else reloadElementResource(target, element, attributes);
|
|
187
|
+
}
|
|
188
|
+
function load(rules, e) {
|
|
189
|
+
var targetInfo = validateTargetInfo(rules, e);
|
|
190
|
+
if (false === targetInfo) return;
|
|
191
|
+
var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url, rule = targetInfo.rule;
|
|
192
|
+
var domain = findCurrentDomain(url, rule);
|
|
193
|
+
var retryTimes = Number(target.dataset.rbRetryTimes) || 0;
|
|
194
|
+
if (0 === retryTimes) return;
|
|
195
|
+
if ('function' == typeof rule.onSuccess) {
|
|
172
196
|
var context = {
|
|
173
|
-
times:
|
|
197
|
+
times: retryTimes,
|
|
174
198
|
domain: domain,
|
|
175
199
|
url: url,
|
|
176
200
|
tagName: tagName,
|
|
177
201
|
isAsyncChunk: false
|
|
178
202
|
};
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
// Then, we will start to retry
|
|
184
|
-
var nextDomain = findNextDomain(domain, config.domain);
|
|
185
|
-
var _target_dataset_rbOriginalQuery;
|
|
186
|
-
// if the initial request is "/static/js/async/src_Hello_tsx.js?q=1", retry url would be "/static/js/async/src_Hello_tsx.js?q=1&retry=1"
|
|
187
|
-
var originalQuery = (_target_dataset_rbOriginalQuery = target.dataset.rbOriginalQuery) !== null && _target_dataset_rbOriginalQuery !== void 0 ? _target_dataset_rbOriginalQuery : getQueryFromUrl(url);
|
|
188
|
-
// this function is the same as async chunk retry
|
|
189
|
-
function getUrlRetryQuery(existRetryTimes) {
|
|
190
|
-
if (config.addQuery === true) {
|
|
191
|
-
return originalQuery !== '' ? "".concat(originalQuery, "&retry=").concat(existRetryTimes) : "?retry=".concat(existRetryTimes);
|
|
192
|
-
}
|
|
193
|
-
if (typeof config.addQuery === 'function') {
|
|
194
|
-
return config.addQuery({
|
|
195
|
-
times: existRetryTimes,
|
|
196
|
-
originalQuery: originalQuery
|
|
197
|
-
});
|
|
203
|
+
rule.onSuccess(context);
|
|
198
204
|
}
|
|
199
|
-
return '';
|
|
200
|
-
}
|
|
201
|
-
// this function is the same as async chunk retry
|
|
202
|
-
function getNextRetryUrl(currRetryUrl, domain, nextDomain, existRetryTimes) {
|
|
203
|
-
return cleanUrl(currRetryUrl.replace(domain, nextDomain)) + getUrlRetryQuery(existRetryTimes + 1);
|
|
204
|
-
}
|
|
205
|
-
var isAsync = Boolean(target.dataset.rbAsync) || target.async || target.defer;
|
|
206
|
-
var attributes = {
|
|
207
|
-
url: getNextRetryUrl(url, domain, nextDomain, existRetryTimes),
|
|
208
|
-
times: existRetryTimes + 1,
|
|
209
|
-
crossOrigin: config.crossOrigin,
|
|
210
|
-
isAsync: isAsync,
|
|
211
|
-
originalQuery: originalQuery
|
|
212
|
-
};
|
|
213
|
-
var element = createElement(target, attributes);
|
|
214
|
-
var context1 = {
|
|
215
|
-
times: existRetryTimes,
|
|
216
|
-
domain: domain,
|
|
217
|
-
url: url,
|
|
218
|
-
tagName: tagName,
|
|
219
|
-
isAsyncChunk: false
|
|
220
|
-
};
|
|
221
|
-
if (typeof config.onRetry === 'function') {
|
|
222
|
-
config.onRetry(context1);
|
|
223
|
-
}
|
|
224
|
-
var _config_delay;
|
|
225
|
-
// Delay retry
|
|
226
|
-
var delayValue = typeof config.delay === 'function' ? config.delay(context1) : (_config_delay = config.delay) !== null && _config_delay !== void 0 ? _config_delay : 0;
|
|
227
|
-
if (delayValue > 0) {
|
|
228
|
-
setTimeout(function() {
|
|
229
|
-
reloadElementResource(target, element, attributes);
|
|
230
|
-
}, delayValue);
|
|
231
|
-
} else {
|
|
232
|
-
reloadElementResource(target, element, attributes);
|
|
233
205
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
var targetInfo = validateTargetInfo(config, e);
|
|
237
|
-
if (targetInfo === false) {
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url;
|
|
241
|
-
var domain = findCurrentDomain(url, config.domain);
|
|
242
|
-
var retryTimes = Number(target.dataset.rbRetryTimes) || 0;
|
|
243
|
-
if (retryTimes === 0) {
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
if (typeof config.onSuccess === 'function') {
|
|
247
|
-
var context = {
|
|
248
|
-
times: retryTimes,
|
|
249
|
-
domain: domain,
|
|
250
|
-
url: url,
|
|
251
|
-
tagName: tagName,
|
|
252
|
-
isAsyncChunk: false
|
|
253
|
-
};
|
|
254
|
-
config.onSuccess(context);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
function resourceMonitor(error, success) {
|
|
258
|
-
if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {
|
|
259
|
-
document.addEventListener('error', function(e) {
|
|
260
|
-
if (e && _instanceof(e.target, Element)) {
|
|
261
|
-
error(e);
|
|
262
|
-
}
|
|
263
|
-
}, true);
|
|
264
|
-
document.addEventListener('load', function(e) {
|
|
265
|
-
if (e && _instanceof(e.target, Element)) {
|
|
266
|
-
success(e);
|
|
267
|
-
}
|
|
268
|
-
}, true);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
// init global variables shared with async chunk
|
|
272
|
-
if (typeof window !== 'undefined' && !window.__RB_ASYNC_CHUNKS__) {
|
|
273
|
-
window.__RB_ASYNC_CHUNKS__ = {};
|
|
274
|
-
}
|
|
275
|
-
// Bind event in window
|
|
276
|
-
try {
|
|
277
|
-
var config = __RUNTIME_GLOBALS_OPTIONS__;
|
|
278
|
-
resourceMonitor(function(e) {
|
|
279
|
-
try {
|
|
280
|
-
retry(config, e);
|
|
281
|
-
} catch (err) {
|
|
282
|
-
console.error('retry error captured', err);
|
|
283
|
-
}
|
|
284
|
-
}, function(e) {
|
|
206
|
+
function registerInitialChunkRetry() {
|
|
207
|
+
if ('undefined' != typeof window && !window.__RB_ASYNC_CHUNKS__) window.__RB_ASYNC_CHUNKS__ = {};
|
|
285
208
|
try {
|
|
286
|
-
|
|
209
|
+
var config = __RETRY_OPTIONS__;
|
|
210
|
+
if ('undefined' != typeof window && void 0 !== window.document) {
|
|
211
|
+
document.addEventListener('error', function(e) {
|
|
212
|
+
if (e && initialChunkRetry_instanceof(e.target, Element)) try {
|
|
213
|
+
retry(config, e);
|
|
214
|
+
} catch (err) {
|
|
215
|
+
console.error('retry error captured', err);
|
|
216
|
+
}
|
|
217
|
+
}, true);
|
|
218
|
+
document.addEventListener('load', function(e) {
|
|
219
|
+
if (e && initialChunkRetry_instanceof(e.target, Element)) try {
|
|
220
|
+
load(config, e);
|
|
221
|
+
} catch (err) {
|
|
222
|
+
console.error('load error captured', err);
|
|
223
|
+
}
|
|
224
|
+
}, true);
|
|
225
|
+
}
|
|
287
226
|
} catch (err) {
|
|
288
|
-
console.error('
|
|
227
|
+
console.error('monitor error captured', err);
|
|
289
228
|
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
229
|
+
}
|
|
230
|
+
registerInitialChunkRetry();
|
|
231
|
+
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e,t){return null!=
|
|
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",
|
|
@@ -28,17 +28,18 @@
|
|
|
28
28
|
"pre-commit": "npm run lint:write"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
+
"@microsoft/api-extractor": "^7.52.8",
|
|
31
32
|
"@biomejs/biome": "^1.9.4",
|
|
32
|
-
"@playwright/test": "^1.53.
|
|
33
|
-
"@rsbuild/core": "^1.
|
|
33
|
+
"@playwright/test": "^1.53.2",
|
|
34
|
+
"@rsbuild/core": "^1.4.2",
|
|
34
35
|
"@rsbuild/plugin-react": "^1.3.2",
|
|
35
|
-
"@rslib/core": "^0.10.
|
|
36
|
-
"@swc/core": "^1.12.
|
|
37
|
-
"@types/node": "^22.15.
|
|
36
|
+
"@rslib/core": "^0.10.4",
|
|
37
|
+
"@swc/core": "^1.12.7",
|
|
38
|
+
"@types/node": "^22.15.34",
|
|
38
39
|
"@types/react": "^19.1.8",
|
|
39
40
|
"@types/react-dom": "^19.1.6",
|
|
40
41
|
"@types/serialize-javascript": "^5.0.4",
|
|
41
|
-
"playwright": "^1.53.
|
|
42
|
+
"playwright": "^1.53.2",
|
|
42
43
|
"react": "^19.1.0",
|
|
43
44
|
"react-dom": "^19.1.0",
|
|
44
45
|
"serialize-javascript": "^6.0.2",
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
"optional": true
|
|
54
55
|
}
|
|
55
56
|
},
|
|
56
|
-
"packageManager": "pnpm@
|
|
57
|
+
"packageManager": "pnpm@10.12.4",
|
|
57
58
|
"publishConfig": {
|
|
58
59
|
"access": "public",
|
|
59
60
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { type Rspack } from '@rsbuild/core';
|
|
2
|
-
import type { PluginAssetsRetryOptions, RuntimeRetryOptions } from './types.js';
|
|
3
|
-
declare class AsyncChunkRetryPlugin implements Rspack.RspackPluginInstance {
|
|
4
|
-
readonly name = "ASYNC_CHUNK_RETRY_PLUGIN";
|
|
5
|
-
readonly options: PluginAssetsRetryOptions & {
|
|
6
|
-
isRspack: boolean;
|
|
7
|
-
};
|
|
8
|
-
readonly runtimeOptions: RuntimeRetryOptions;
|
|
9
|
-
constructor(options: PluginAssetsRetryOptions & {
|
|
10
|
-
isRspack: boolean;
|
|
11
|
-
});
|
|
12
|
-
getRawRuntimeRetryCode(): string;
|
|
13
|
-
apply(compiler: Rspack.Compiler): void;
|
|
14
|
-
}
|
|
15
|
-
export { AsyncChunkRetryPlugin };
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
type ChunkId = string;
|
|
2
|
-
type ChunkFilename = string;
|
|
3
|
-
type ChunkSrcUrl = string;
|
|
4
|
-
type EnsureChunk = (chunkId: ChunkId, ...args: unknown[]) => Promise<unknown>;
|
|
5
|
-
type LoadScript = (url: ChunkSrcUrl, done: unknown, key: string, chunkId: ChunkId, ...args: unknown[]) => void;
|
|
6
|
-
type LoadStyleSheet = (href: string, chunkId: ChunkId) => string;
|
|
7
|
-
declare global {
|
|
8
|
-
var __RUNTIME_GLOBALS_REQUIRE__: unknown;
|
|
9
|
-
var __RUNTIME_GLOBALS_ENSURE_CHUNK__: EnsureChunk;
|
|
10
|
-
var __RUNTIME_GLOBALS_GET_CHUNK_SCRIPT_FILENAME__: (chunkId: ChunkId, ...args: unknown[]) => string;
|
|
11
|
-
var __RUNTIME_GLOBALS_GET_CSS_FILENAME__: ((chunkId: ChunkId, ...args: unknown[]) => string) | undefined;
|
|
12
|
-
var __RUNTIME_GLOBALS_GET_MINI_CSS_EXTRACT_FILENAME__: ((chunkId: ChunkId, ...args: unknown[]) => string) | undefined;
|
|
13
|
-
var __RUNTIME_GLOBALS_LOAD_SCRIPT__: LoadScript;
|
|
14
|
-
var __RUNTIME_GLOBALS_RSBUILD_LOAD_STYLESHEET__: LoadStyleSheet;
|
|
15
|
-
var __RUNTIME_GLOBALS_PUBLIC_PATH__: string;
|
|
16
|
-
var __RETRY_OPTIONS__: RuntimeRetryOptions;
|
|
17
|
-
var __RB_ASYNC_CHUNKS__: Record<ChunkFilename, boolean>;
|
|
18
|
-
}
|
|
19
|
-
export {};
|