@rsbuild/plugin-assets-retry 1.2.3 → 1.3.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.
@@ -1,293 +1,208 @@
1
- // rsbuild/runtime/initial-chunk-retry
2
- function _instanceof(left, right) {
3
- if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
4
- return !!right[Symbol.hasInstance](left);
5
- } else {
6
- return left instanceof right;
7
- }
8
- }
9
- var TAG_TYPE = {
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) {
1
+ (function() {
2
+ "use strict";
3
+ var ERROR_PREFIX = '[@rsbuild/plugin-assets-retry] ';
4
+ function findCurrentDomain(url, config) {
5
+ var domains = config.domain;
6
+ var domain = '';
7
+ for(var i = 0; i < domains.length; i++)if (-1 !== url.indexOf(domains[i])) {
19
8
  domain = domains[i];
20
9
  break;
21
10
  }
11
+ return domain || window.origin;
22
12
  }
23
- return domain || window.origin;
24
- }
25
- // this function is the same as async chunk retry
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;
13
+ function findNextDomain(url, config) {
14
+ var domains = config.domain;
15
+ var currentDomain = findCurrentDomain(url, config);
16
+ var index = domains.indexOf(currentDomain);
17
+ return domains[(index + 1) % domains.length] || url;
40
18
  }
41
- if (_instanceof(element, HTMLLinkElement)) {
42
- var _element_getAttribute1;
43
- // For <link href="" />
44
- if (!((_element_getAttribute1 = element.getAttribute('href')) === null || _element_getAttribute1 === void 0 ? void 0 : _element_getAttribute1.trim())) {
45
- return null;
46
- }
47
- return element.href;
19
+ var postfixRE = /[?#].*$/;
20
+ function cleanUrl(url) {
21
+ return url.replace(postfixRE, '');
48
22
  }
49
- return null;
50
- }
51
- function validateTargetInfo(config, e) {
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;
23
+ function getQueryFromUrl(url) {
24
+ var parts = url.split('?')[1];
25
+ return parts ? "?".concat(parts.split('#')[0]) : '';
58
26
  }
59
- return {
60
- target: target,
61
- tagName: tagName,
62
- url: url
63
- };
64
- }
65
- var postfixRE = /[?#].*$/;
66
- function cleanUrl(url) {
67
- return url.replace(postfixRE, '');
68
- }
69
- function getQueryFromUrl(url) {
70
- var parts = url.split('?')[1];
71
- return parts ? "?".concat(parts.split('#')[0]) : '';
72
- }
73
- function createElement(origin, attributes) {
74
- var crossOrigin = attributes.crossOrigin === true ? 'anonymous' : attributes.crossOrigin;
75
- var crossOriginAttr = crossOrigin ? 'crossorigin="'.concat(crossOrigin, '"') : '';
76
- var retryTimesAttr = attributes.times ? 'data-rb-retry-times="'.concat(attributes.times, '"') : '';
77
- var originalQueryAttr = attributes.originalQuery ? 'data-rb-original-query="'.concat(attributes.originalQuery, '"') : '';
78
- var isAsyncAttr = attributes.isAsync ? 'data-rb-async' : '';
79
- if (_instanceof(origin, HTMLScriptElement)) {
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
- }
94
- return {
95
- element: script,
96
- str: // biome-ignore lint/style/useTemplate: use "</" + "script>" instead of script tag to avoid syntax error when inlining in html
97
- '<script src="'.concat(attributes.url, '" ').concat(crossOriginAttr, " ").concat(retryTimesAttr, " ").concat(isAsyncAttr, " ").concat(originalQueryAttr, ">") + '</' + 'script>'
98
- };
27
+ function getUrlRetryQuery(existRetryTimes, originalQuery, config) {
28
+ if (true === config.addQuery) return '' !== originalQuery ? "".concat(originalQuery, "&retry=").concat(existRetryTimes) : "?retry=".concat(existRetryTimes);
29
+ if ('function' == typeof config.addQuery) return config.addQuery({
30
+ times: existRetryTimes,
31
+ originalQuery: originalQuery
32
+ });
33
+ return '';
99
34
  }
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
- }
35
+ function getNextRetryUrl(currRetryUrl, domain, nextDomain, existRetryTimes, originalQuery, config) {
36
+ return cleanUrl(currRetryUrl.replace(domain, nextDomain)) + getUrlRetryQuery(existRetryTimes + 1, originalQuery, config);
37
+ }
38
+ function _instanceof(left, right) {
39
+ if (null != right && "undefined" != typeof Symbol && right[Symbol.hasInstance]) return !!right[Symbol.hasInstance](left);
40
+ return left instanceof right;
41
+ }
42
+ var TAG_TYPE = {
43
+ link: HTMLLinkElement,
44
+ script: HTMLScriptElement,
45
+ img: HTMLImageElement
46
+ };
47
+ function getRequestUrl(element) {
48
+ if (_instanceof(element, HTMLScriptElement) || _instanceof(element, HTMLImageElement)) return element.src;
49
+ if (_instanceof(element, HTMLLinkElement)) return element.href;
50
+ return null;
51
+ }
52
+ function validateTargetInfo(config, e) {
53
+ var target = e.target;
54
+ var tagName = target.tagName.toLocaleLowerCase();
55
+ var allowTags = config.type;
56
+ var url = getRequestUrl(target);
57
+ if (!tagName || -1 === allowTags.indexOf(tagName) || !TAG_TYPE[tagName] || !_instanceof(target, TAG_TYPE[tagName]) || !url) return false;
116
58
  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>")
59
+ target: target,
60
+ tagName: tagName,
61
+ url: url
119
62
  };
120
63
  }
121
- }
122
- function reloadElementResource(origin, fresh, attributes) {
123
- if (_instanceof(origin, HTMLScriptElement)) {
124
- if (attributes.isAsync) {
125
- document.body.appendChild(fresh.element);
126
- } else {
127
- document.write(fresh.str);
64
+ function createElement(origin, attributes) {
65
+ var crossOrigin = true === attributes.crossOrigin ? 'anonymous' : attributes.crossOrigin;
66
+ var crossOriginAttr = crossOrigin ? 'crossorigin="'.concat(crossOrigin, '"') : '';
67
+ var retryTimesAttr = attributes.times ? 'data-rb-retry-times="'.concat(attributes.times, '"') : '';
68
+ var originalQueryAttr = attributes.originalQuery ? 'data-rb-original-query="'.concat(attributes.originalQuery, '"') : '';
69
+ var isAsyncAttr = attributes.isAsync ? 'data-rb-async' : '';
70
+ if (_instanceof(origin, HTMLScriptElement)) {
71
+ var script = document.createElement("script");
72
+ script.src = attributes.url;
73
+ if (crossOrigin) script.crossOrigin = crossOrigin;
74
+ if (attributes.times) script.dataset.rbRetryTimes = String(attributes.times);
75
+ if (attributes.isAsync) script.dataset.rbAsync = '';
76
+ if (void 0 !== attributes.originalQuery) script.dataset.rbOriginalQuery = attributes.originalQuery;
77
+ return {
78
+ element: script,
79
+ str: '<script src="'.concat(attributes.url, '" ').concat(crossOriginAttr, " ").concat(retryTimesAttr, " ").concat(isAsyncAttr, " ").concat(originalQueryAttr, ">") + "<\/script>"
80
+ };
128
81
  }
129
- }
130
- if (_instanceof(origin, HTMLLinkElement)) {
131
- document.getElementsByTagName('head')[0].appendChild(fresh.element);
132
- }
133
- if (_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(config, e) {
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);
82
+ if (_instanceof(origin, HTMLLinkElement)) {
83
+ var link = document.createElement('link');
84
+ link.rel = origin.rel || 'stylesheet';
85
+ if (origin.as) link.as = origin.as;
86
+ link.href = attributes.url;
87
+ if (crossOrigin) link.crossOrigin = crossOrigin;
88
+ if (attributes.times) link.dataset.rbRetryTimes = String(attributes.times);
89
+ if (void 0 !== attributes.originalQuery) link.dataset.rbOriginalQuery = attributes.originalQuery;
90
+ return {
91
+ 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>")
158
93
  };
159
94
  }
160
- if (typeof tester !== 'function' || !tester(url)) {
95
+ }
96
+ function reloadElementResource(origin, fresh, attributes) {
97
+ if (_instanceof(origin, HTMLScriptElement)) if (attributes.isAsync) document.body.appendChild(fresh.element);
98
+ else console.warn(ERROR_PREFIX, "load sync script failed, for security only async/defer script can be retried", origin);
99
+ if (_instanceof(origin, HTMLLinkElement)) document.getElementsByTagName('head')[0].appendChild(fresh.element);
100
+ if (_instanceof(origin, HTMLImageElement)) {
101
+ origin.src = attributes.url;
102
+ origin.dataset.rbRetryTimes = String(attributes.times);
103
+ origin.dataset.rbOriginalQuery = String(attributes.originalQuery);
104
+ }
105
+ }
106
+ function retry(config, e) {
107
+ var targetInfo = validateTargetInfo(config, e);
108
+ if (false === targetInfo) return;
109
+ var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url;
110
+ if ('undefined' != typeof window && Object.keys(window.__RB_ASYNC_CHUNKS__ || {}).some(function(chunkName) {
111
+ return -1 !== url.indexOf(chunkName);
112
+ })) return;
113
+ var tester = config.test;
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;
125
+ var existRetryTimes = Number(target.dataset.rbRetryTimes) || 0;
126
+ if (existRetryTimes === config.max) {
127
+ if ('function' == typeof config.onFail) {
128
+ var context = {
129
+ times: existRetryTimes,
130
+ domain: domain,
131
+ url: url,
132
+ tagName: tagName,
133
+ isAsyncChunk: false
134
+ };
135
+ config.onFail(context);
136
+ }
161
137
  return;
162
138
  }
163
- }
164
- var domain = findCurrentDomain(url, config.domain);
165
- if (config.domain && config.domain.length > 0 && config.domain.indexOf(domain) === -1) {
166
- return;
167
- }
168
- // If the retry times has exceeded the maximum, fail
169
- var existRetryTimes = Number(target.dataset.rbRetryTimes) || 0;
170
- if (existRetryTimes === config.max) {
171
- if (typeof config.onFail === 'function') {
139
+ var nextDomain = findNextDomain(domain, config);
140
+ var _target_dataset_rbOriginalQuery;
141
+ var originalQuery = null != (_target_dataset_rbOriginalQuery = target.dataset.rbOriginalQuery) ? _target_dataset_rbOriginalQuery : getQueryFromUrl(url);
142
+ var isAsync = Boolean(target.dataset.rbAsync) || target.async || target.defer;
143
+ var attributes = {
144
+ url: getNextRetryUrl(url, domain, nextDomain, existRetryTimes, originalQuery, config),
145
+ times: existRetryTimes + 1,
146
+ crossOrigin: config.crossOrigin,
147
+ isAsync: isAsync,
148
+ originalQuery: originalQuery
149
+ };
150
+ var element = createElement(target, attributes);
151
+ var context1 = {
152
+ times: existRetryTimes,
153
+ domain: domain,
154
+ url: url,
155
+ tagName: tagName,
156
+ isAsyncChunk: false
157
+ };
158
+ if ('function' == typeof config.onRetry) config.onRetry(context1);
159
+ var delayValue = 'function' == typeof config.delay ? config.delay(context1) : config.delay;
160
+ if (delayValue > 0) setTimeout(function() {
161
+ reloadElementResource(target, element, attributes);
162
+ }, delayValue);
163
+ else reloadElementResource(target, element, attributes);
164
+ }
165
+ function load(config, e) {
166
+ var targetInfo = validateTargetInfo(config, e);
167
+ if (false === targetInfo) return;
168
+ var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url;
169
+ var domain = findCurrentDomain(url, config);
170
+ var retryTimes = Number(target.dataset.rbRetryTimes) || 0;
171
+ if (0 === retryTimes) return;
172
+ if ('function' == typeof config.onSuccess) {
172
173
  var context = {
173
- times: existRetryTimes,
174
+ times: retryTimes,
174
175
  domain: domain,
175
176
  url: url,
176
177
  tagName: tagName,
177
178
  isAsyncChunk: false
178
179
  };
179
- config.onFail(context);
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
- });
180
+ config.onSuccess(context);
198
181
  }
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
182
  }
234
- }
235
- function load(config, e) {
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) {
183
+ function registerInitialChunkRetry() {
184
+ if ('undefined' != typeof window && !window.__RB_ASYNC_CHUNKS__) window.__RB_ASYNC_CHUNKS__ = {};
285
185
  try {
286
- load(config, e);
186
+ var config = __RETRY_OPTIONS__;
187
+ if ('undefined' != typeof window && void 0 !== window.document) {
188
+ document.addEventListener('error', function(e) {
189
+ if (e && _instanceof(e.target, Element)) try {
190
+ retry(config, e);
191
+ } catch (err) {
192
+ console.error('retry error captured', err);
193
+ }
194
+ }, true);
195
+ document.addEventListener('load', function(e) {
196
+ if (e && _instanceof(e.target, Element)) try {
197
+ load(config, e);
198
+ } catch (err) {
199
+ console.error('load error captured', err);
200
+ }
201
+ }, true);
202
+ }
287
203
  } catch (err) {
288
- console.error('load error captured', err);
204
+ console.error('monitor error captured', err);
289
205
  }
290
- });
291
- } catch (err) {
292
- console.error('monitor error captured', err);
293
- }
206
+ }
207
+ registerInitialChunkRetry();
208
+ })();
@@ -1 +1 @@
1
- function e(e,t){return null!=t&&"undefined"!=typeof Symbol&&t[Symbol.hasInstance]?!!t[Symbol.hasInstance](e):e instanceof t}var t={link:HTMLLinkElement,script:HTMLScriptElement,img:HTMLImageElement};function n(e,t){for(var n="",r=0;r<t.length;r++)if(-1!==e.indexOf(t[r])){n=t[r];break}return n||window.origin}function r(n,r){var i,a,o,c=r.target,s=c.tagName.toLocaleLowerCase(),l=n.type,u=e(i=c,HTMLScriptElement)||e(i,HTMLImageElement)?(null==(a=i.getAttribute("src"))?void 0:a.trim())?i.src:null:e(i,HTMLLinkElement)?(null==(o=i.getAttribute("href"))?void 0:o.trim())?i.href:null:null;return!!s&&-1!==l.indexOf(s)&&!!t[s]&&!!e(c,t[s])&&!!u&&{target:c,tagName:s,url:u}}var i=/[?#].*$/;function a(t,n,r){e(t,HTMLScriptElement)&&(r.isAsync?document.body.appendChild(n.element):document.write(n.str)),e(t,HTMLLinkElement)&&document.getElementsByTagName("head")[0].appendChild(n.element),e(t,HTMLImageElement)&&(t.src=r.url,t.dataset.rbRetryTimes=String(r.times),t.dataset.rbOriginalQuery=String(r.originalQuery))}"undefined"==typeof window||window.__RB_ASYNC_CHUNKS__||(window.__RB_ASYNC_CHUNKS__={});try{var o,c,s=__RUNTIME_GLOBALS_OPTIONS__;o=function(t){try{!function(t,o){var c,s,l=r(t,o);if(!1!==l){var u=l.target,d=l.tagName,m=l.url;if(!("undefined"!=typeof window&&Object.keys(window.__RB_ASYNC_CHUNKS__||{}).some(function(e){return -1!==m.indexOf(e)}))){var y=t.test;if(y){if("string"==typeof y){var f=new RegExp(y);y=function(e){return f.test(e)}}if("function"!=typeof y||!y(m))return}var g=n(m,t.domain);if(!t.domain||!(t.domain.length>0)||-1!==t.domain.indexOf(g)){var p,v,b,_,L,S,E,T,h,w=Number(u.dataset.rbRetryTimes)||0;if(w===t.max){"function"==typeof t.onFail&&t.onFail({times:w,domain:g,url:m,tagName:d,isAsyncChunk:!1});return}var O=(E=n(g,S=t.domain),T=S.indexOf(E),S[(T+1)%S.length]||g),N=null!=(c=u.dataset.rbOriginalQuery)?c:(h=m.split("?")[1])?"?".concat(h.split("#")[0]):"",Q=!!u.dataset.rbAsync||u.async||u.defer,A={url:(p=m,v=g,b=O,_=w,p.replace(v,b).replace(i,"")+(L=_+1,!0===t.addQuery?""!==N?"".concat(N,"&retry=").concat(L):"?retry=".concat(L):"function"==typeof t.addQuery?t.addQuery({times:L,originalQuery:N}):"")),times:w+1,crossOrigin:t.crossOrigin,isAsync:Q,originalQuery:N},H=function(t,n){var r=!0===n.crossOrigin?"anonymous":n.crossOrigin,i=r?'crossorigin="'.concat(r,'"'):"",a=n.times?'data-rb-retry-times="'.concat(n.times,'"'):"",o=n.originalQuery?'data-rb-original-query="'.concat(n.originalQuery,'"'):"",c=n.isAsync?"data-rb-async":"";if(e(t,HTMLScriptElement)){var s=document.createElement("script");return s.src=n.url,r&&(s.crossOrigin=r),n.times&&(s.dataset.rbRetryTimes=String(n.times)),n.isAsync&&(s.dataset.rbAsync=""),void 0!==n.originalQuery&&(s.dataset.rbOriginalQuery=n.originalQuery),{element:s,str:'<script src="'.concat(n.url,'" ').concat(i," ").concat(a," ").concat(c," ").concat(o,">")+"<\/script>"}}if(e(t,HTMLLinkElement)){var l=document.createElement("link");return l.rel=t.rel||"stylesheet",t.as&&(l.as=t.as),l.href=n.url,r&&(l.crossOrigin=r),n.times&&(l.dataset.rbRetryTimes=String(n.times)),void 0!==n.originalQuery&&(l.dataset.rbOriginalQuery=n.originalQuery),{element:l,str:'<link rel="'.concat(l.rel,'" href="').concat(n.url,'" ').concat(i," ").concat(a," ").concat(l.as?'as="'.concat(l.as,'"'):""," ").concat(o,"></link>")}}}(u,A),k={times:w,domain:g,url:m,tagName:d,isAsyncChunk:!1};"function"==typeof t.onRetry&&t.onRetry(k);var C="function"==typeof t.delay?t.delay(k):null!=(s=t.delay)?s:0;C>0?setTimeout(function(){a(u,H,A)},C):a(u,H,A)}}}}(s,t)}catch(e){console.error("retry error captured",e)}},c=function(e){try{!function(e,t){var i=r(e,t);if(!1!==i){var a=i.target,o=i.tagName,c=i.url,s=n(c,e.domain),l=Number(a.dataset.rbRetryTimes)||0;0!==l&&"function"==typeof e.onSuccess&&e.onSuccess({times:l,domain:s,url:c,tagName:o,isAsyncChunk:!1})}}(s,e)}catch(e){console.error("load error captured",e)}},"undefined"!=typeof window&&void 0!==window.document&&(document.addEventListener("error",function(t){t&&e(t.target,Element)&&o(t)},!0),document.addEventListener("load",function(t){t&&e(t.target,Element)&&c(t)},!0))}catch(e){console.error("monitor error captured",e)}
1
+ !function(){"use strict";function e(e,t){for(var n=t.domain,r="",i=0;i<n.length;i++)if(-1!==e.indexOf(n[i])){r=n[i];break}return r||window.origin}var t=/[?#].*$/;function n(e,t){return null!=t&&"undefined"!=typeof Symbol&&t[Symbol.hasInstance]?!!t[Symbol.hasInstance](e):e instanceof t}var r={link:HTMLLinkElement,script:HTMLScriptElement,img:HTMLImageElement};function i(e,t){var i=t.target,a=i.tagName.toLocaleLowerCase(),o=e.type,c=n(i,HTMLScriptElement)||n(i,HTMLImageElement)?i.src:n(i,HTMLLinkElement)?i.href:null;return!!a&&-1!==o.indexOf(a)&&!!r[a]&&!!n(i,r[a])&&!!c&&{target:i,tagName:a,url:c}}function a(e,t,r){n(e,HTMLScriptElement)&&(r.isAsync?document.body.appendChild(t.element):console.warn("[@rsbuild/plugin-assets-retry] ","load sync script failed, for security only async/defer script can be retried",e)),n(e,HTMLLinkElement)&&document.getElementsByTagName("head")[0].appendChild(t.element),n(e,HTMLImageElement)&&(e.src=r.url,e.dataset.rbRetryTimes=String(r.times),e.dataset.rbOriginalQuery=String(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&&n(r.target,Element))try{!function(r,o){var c,s=i(r,o);if(!1!==s){var l=s.target,u=s.tagName,d=s.url;if(!("undefined"!=typeof window&&Object.keys(window.__RB_ASYNC_CHUNKS__||{}).some(function(e){return -1!==d.indexOf(e)}))){var m=r.test;if(m){if("string"==typeof m){var y=new RegExp(m);m=function(e){return y.test(e)}}if("function"!=typeof m||!m(d))return}var f=e(d,r);if(!r.domain||!(r.domain.length>0)||-1!==r.domain.indexOf(f)){var g,p,b,v,_=Number(l.dataset.rbRetryTimes)||0;if(_===r.max){"function"==typeof r.onFail&&r.onFail({times:_,domain:f,url:d,tagName:u,isAsyncChunk:!1});return}var E=(g=r.domain,p=e(f,r),b=g.indexOf(p),g[(b+1)%g.length]||f),S=null!=(c=l.dataset.rbOriginalQuery)?c:(v=d.split("?")[1])?"?".concat(v.split("#")[0]):"",T=!!l.dataset.rbAsync||l.async||l.defer,w={url:function(e,n,r,i,a,o){var c;return e.replace(n,r).replace(t,"")+(c=i+1,!0===o.addQuery?""!==a?"".concat(a,"&retry=").concat(c):"?retry=".concat(c):"function"==typeof o.addQuery?o.addQuery({times:c,originalQuery:a}):"")}(d,f,E,_,S,r),times:_+1,crossOrigin:r.crossOrigin,isAsync:T,originalQuery:S},L=function(e,t){var r=!0===t.crossOrigin?"anonymous":t.crossOrigin,i=r?'crossorigin="'.concat(r,'"'):"",a=t.times?'data-rb-retry-times="'.concat(t.times,'"'):"",o=t.originalQuery?'data-rb-original-query="'.concat(t.originalQuery,'"'):"",c=t.isAsync?"data-rb-async":"";if(n(e,HTMLScriptElement)){var s=document.createElement("script");return s.src=t.url,r&&(s.crossOrigin=r),t.times&&(s.dataset.rbRetryTimes=String(t.times)),t.isAsync&&(s.dataset.rbAsync=""),void 0!==t.originalQuery&&(s.dataset.rbOriginalQuery=t.originalQuery),{element:s,str:'<script src="'.concat(t.url,'" ').concat(i," ").concat(a," ").concat(c," ").concat(o,">")+"<\/script>"}}if(n(e,HTMLLinkElement)){var l=document.createElement("link");return l.rel=e.rel||"stylesheet",e.as&&(l.as=e.as),l.href=t.url,r&&(l.crossOrigin=r),t.times&&(l.dataset.rbRetryTimes=String(t.times)),void 0!==t.originalQuery&&(l.dataset.rbOriginalQuery=t.originalQuery),{element:l,str:'<link rel="'.concat(l.rel,'" href="').concat(t.url,'" ').concat(i," ").concat(a," ").concat(l.as?'as="'.concat(l.as,'"'):""," ").concat(o,"></link>")}}}(l,w),h={times:_,domain:f,url:d,tagName:u,isAsyncChunk:!1};"function"==typeof r.onRetry&&r.onRetry(h);var O="function"==typeof r.delay?r.delay(h):r.delay;O>0?setTimeout(function(){a(l,L,w)},O):a(l,L,w)}}}}(o,r)}catch(e){console.error("retry error captured",e)}},!0),document.addEventListener("load",function(t){if(t&&n(t.target,Element))try{!function(t,n){var r=i(t,n);if(!1!==r){var a=r.target,o=r.tagName,c=r.url,s=e(c,t),l=Number(a.dataset.rbRetryTimes)||0;0!==l&&"function"==typeof t.onSuccess&&t.onSuccess({times:l,domain:s,url:c,tagName:o,isAsyncChunk:!1})}}(o,t)}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.2.3",
3
+ "version": "1.3.0",
4
4
  "repository": "https://github.com/rspack-contrib/rsbuild-plugin-assets-retry",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,6 +28,7 @@
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
33
  "@playwright/test": "^1.53.0",
33
34
  "@rsbuild/core": "^1.3.22",
@@ -53,7 +54,7 @@
53
54
  "optional": true
54
55
  }
55
56
  },
56
- "packageManager": "pnpm@9.15.9",
57
+ "packageManager": "pnpm@10.12.2",
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 {};
@@ -1,5 +0,0 @@
1
- declare global {
2
- var __RB_ASYNC_CHUNKS__: Record<string, boolean>;
3
- var __RUNTIME_GLOBALS_OPTIONS__: RuntimeRetryOptions;
4
- }
5
- export {};
package/dist/types.d.ts DELETED
@@ -1,72 +0,0 @@
1
- import type { CrossOrigin } from '@rsbuild/core';
2
- export type PluginAssetsRetryOptions = {
3
- /**
4
- * The maximum number of retries for a single asset.
5
- * @default 3
6
- */
7
- max?: number;
8
- /**
9
- * Used to specify the HTML tag types that need to be retried.
10
- * @default ['script', 'link', 'img']
11
- */
12
- type?: string[];
13
- /**
14
- * The test function of the asset to be retried.
15
- */
16
- test?: string | ((url: string) => boolean);
17
- /**
18
- * Specifies the retry domain when assets fail to load.
19
- */
20
- domain?: string[];
21
- /**
22
- * Set the `crossorigin` attribute for tags.
23
- * @default config.html.crossorigin
24
- */
25
- crossOrigin?: boolean | CrossOrigin;
26
- /**
27
- * The callback function when the asset is failed to be retried.
28
- */
29
- onFail?: (context: AssetsRetryHookContext) => void;
30
- /**
31
- * The callback function when the asset is being retried.
32
- */
33
- onRetry?: (context: AssetsRetryHookContext) => void;
34
- /**
35
- * The callback function when the asset is successfully retried.
36
- */
37
- onSuccess?: (context: AssetsRetryHookContext) => void;
38
- /**
39
- * The function to add query parameters to the URL of the asset being retried.
40
- * @param times e.g: 1 -> 2 -> 3
41
- * @param originalQuery initial request url's query e.g: <script src="https://cdn.com/a.js?version=1"></script> -> "?version=1"
42
- * @default false
43
- * @description true -> hasQuery(originalQuery) ? `${getQuery(originalQuery)}&retry=${existRetryTimes}` : `?retry=${existRetryTimes}`
44
- */
45
- addQuery?: boolean | ((context: {
46
- times: number;
47
- originalQuery: string;
48
- }) => string);
49
- /**
50
- * Whether to inline the runtime JavaScript code of Assets Retry plugin into the HTML file.
51
- * @default true
52
- */
53
- inlineScript?: boolean;
54
- /**
55
- * Whether to minify the runtime JavaScript code of Assets Retry plugin.
56
- * @default rsbuildConfig.mode === 'production'
57
- */
58
- minify?: boolean;
59
- /**
60
- * The delay time between retries. Unit: ms
61
- * @default 0
62
- */
63
- delay?: number | ((context: AssetsRetryHookContext) => number);
64
- };
65
- export type RuntimeRetryOptions = Omit<PluginAssetsRetryOptions, 'inlineScript' | 'minify'>;
66
- export type AssetsRetryHookContext = {
67
- url: string;
68
- times: number;
69
- domain: string;
70
- tagName: string;
71
- isAsyncChunk: boolean;
72
- };