@rsbuild/plugin-assets-retry 1.2.2 → 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,291 +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
- // For <script src="" /> or <img src="" />
34
- // element.getAttribute('src') === '' but element.src === baseURI
35
- if (!element.getAttribute('src')) {
36
- return null;
37
- }
38
- 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;
39
18
  }
40
- if (_instanceof(element, HTMLLinkElement)) {
41
- // For <link href="" />
42
- if (!element.getAttribute('href')) {
43
- return null;
44
- }
45
- return element.href;
19
+ var postfixRE = /[?#].*$/;
20
+ function cleanUrl(url) {
21
+ return url.replace(postfixRE, '');
46
22
  }
47
- return null;
48
- }
49
- function validateTargetInfo(config, e) {
50
- var target = e.target;
51
- var tagName = target.tagName.toLocaleLowerCase();
52
- var allowTags = config.type;
53
- var url = getRequestUrl(target);
54
- if (!tagName || allowTags.indexOf(tagName) === -1 || !TAG_TYPE[tagName] || !_instanceof(target, TAG_TYPE[tagName]) || !url) {
55
- return false;
23
+ function getQueryFromUrl(url) {
24
+ var parts = url.split('?')[1];
25
+ return parts ? "?".concat(parts.split('#')[0]) : '';
56
26
  }
57
- return {
58
- target: target,
59
- tagName: tagName,
60
- url: url
61
- };
62
- }
63
- var postfixRE = /[?#].*$/;
64
- function cleanUrl(url) {
65
- return url.replace(postfixRE, '');
66
- }
67
- function getQueryFromUrl(url) {
68
- var parts = url.split('?')[1];
69
- return parts ? "?".concat(parts.split('#')[0]) : '';
70
- }
71
- function createElement(origin, attributes) {
72
- var crossOrigin = attributes.crossOrigin === true ? 'anonymous' : attributes.crossOrigin;
73
- var crossOriginAttr = crossOrigin ? 'crossorigin="'.concat(crossOrigin, '"') : '';
74
- var retryTimesAttr = attributes.times ? 'data-rb-retry-times="'.concat(attributes.times, '"') : '';
75
- var originalQueryAttr = attributes.originalQuery ? 'data-rb-original-query="'.concat(attributes.originalQuery, '"') : '';
76
- var isAsyncAttr = attributes.isAsync ? 'data-rb-async' : '';
77
- if (_instanceof(origin, HTMLScriptElement)) {
78
- var script = document.createElement('script');
79
- script.src = attributes.url;
80
- if (crossOrigin) {
81
- script.crossOrigin = crossOrigin;
82
- }
83
- if (attributes.times) {
84
- script.dataset.rbRetryTimes = String(attributes.times);
85
- }
86
- if (attributes.isAsync) {
87
- script.dataset.rbAsync = '';
88
- }
89
- if (attributes.originalQuery !== undefined) {
90
- script.dataset.rbOriginalQuery = attributes.originalQuery;
91
- }
92
- return {
93
- element: script,
94
- str: // biome-ignore lint/style/useTemplate: use "</" + "script>" instead of script tag to avoid syntax error when inlining in html
95
- '<script src="'.concat(attributes.url, '" ').concat(crossOriginAttr, " ").concat(retryTimesAttr, " ").concat(isAsyncAttr, " ").concat(originalQueryAttr, ">") + '</' + 'script>'
96
- };
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 '';
97
34
  }
98
- if (_instanceof(origin, HTMLLinkElement)) {
99
- var link = document.createElement('link');
100
- link.rel = origin.rel || 'stylesheet';
101
- if (origin.as) {
102
- link.as = origin.as;
103
- }
104
- link.href = attributes.url;
105
- if (crossOrigin) {
106
- link.crossOrigin = crossOrigin;
107
- }
108
- if (attributes.times) {
109
- link.dataset.rbRetryTimes = String(attributes.times);
110
- }
111
- if (attributes.originalQuery !== undefined) {
112
- link.dataset.rbOriginalQuery = attributes.originalQuery;
113
- }
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;
114
58
  return {
115
- element: link,
116
- 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
117
62
  };
118
63
  }
119
- }
120
- function reloadElementResource(origin, fresh, attributes) {
121
- if (_instanceof(origin, HTMLScriptElement)) {
122
- if (attributes.isAsync) {
123
- document.body.appendChild(fresh.element);
124
- } else {
125
- 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
+ };
126
81
  }
127
- }
128
- if (_instanceof(origin, HTMLLinkElement)) {
129
- document.getElementsByTagName('head')[0].appendChild(fresh.element);
130
- }
131
- if (_instanceof(origin, HTMLImageElement)) {
132
- origin.src = attributes.url;
133
- origin.dataset.rbRetryTimes = String(attributes.times);
134
- origin.dataset.rbOriginalQuery = String(attributes.originalQuery);
135
- }
136
- }
137
- function retry(config, e) {
138
- var targetInfo = validateTargetInfo(config, e);
139
- if (targetInfo === false) {
140
- return;
141
- }
142
- var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url;
143
- // If the requested failed chunk is async chunk,skip it, because async chunk will be retried by asyncChunkRetry runtime
144
- if (typeof window !== 'undefined' && Object.keys(window.__RB_ASYNC_CHUNKS__ || {}).some(function(chunkName) {
145
- return url.indexOf(chunkName) !== -1;
146
- })) {
147
- return;
148
- }
149
- // Filter by config.test and config.domain
150
- var tester = config.test;
151
- if (tester) {
152
- if (typeof tester === 'string') {
153
- var regexp = new RegExp(tester);
154
- tester = function(str) {
155
- 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>")
156
93
  };
157
94
  }
158
- 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
+ }
159
137
  return;
160
138
  }
161
- }
162
- var domain = findCurrentDomain(url, config.domain);
163
- if (config.domain && config.domain.length > 0 && config.domain.indexOf(domain) === -1) {
164
- return;
165
- }
166
- // If the retry times has exceeded the maximum, fail
167
- var existRetryTimes = Number(target.dataset.rbRetryTimes) || 0;
168
- if (existRetryTimes === config.max) {
169
- 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) {
170
173
  var context = {
171
- times: existRetryTimes,
174
+ times: retryTimes,
172
175
  domain: domain,
173
176
  url: url,
174
177
  tagName: tagName,
175
178
  isAsyncChunk: false
176
179
  };
177
- config.onFail(context);
178
- }
179
- return;
180
- }
181
- // Then, we will start to retry
182
- var nextDomain = findNextDomain(domain, config.domain);
183
- var _target_dataset_rbOriginalQuery;
184
- // 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"
185
- var originalQuery = (_target_dataset_rbOriginalQuery = target.dataset.rbOriginalQuery) !== null && _target_dataset_rbOriginalQuery !== void 0 ? _target_dataset_rbOriginalQuery : getQueryFromUrl(url);
186
- // this function is the same as async chunk retry
187
- function getUrlRetryQuery(existRetryTimes) {
188
- if (config.addQuery === true) {
189
- return originalQuery !== '' ? "".concat(originalQuery, "&retry=").concat(existRetryTimes) : "?retry=".concat(existRetryTimes);
190
- }
191
- if (typeof config.addQuery === 'function') {
192
- return config.addQuery({
193
- times: existRetryTimes,
194
- originalQuery: originalQuery
195
- });
180
+ config.onSuccess(context);
196
181
  }
197
- return '';
198
- }
199
- // this function is the same as async chunk retry
200
- function getNextRetryUrl(currRetryUrl, domain, nextDomain, existRetryTimes) {
201
- return cleanUrl(currRetryUrl.replace(domain, nextDomain)) + getUrlRetryQuery(existRetryTimes + 1);
202
- }
203
- var isAsync = Boolean(target.dataset.rbAsync) || target.async || target.defer;
204
- var attributes = {
205
- url: getNextRetryUrl(url, domain, nextDomain, existRetryTimes),
206
- times: existRetryTimes + 1,
207
- crossOrigin: config.crossOrigin,
208
- isAsync: isAsync,
209
- originalQuery: originalQuery
210
- };
211
- var element = createElement(target, attributes);
212
- var context1 = {
213
- times: existRetryTimes,
214
- domain: domain,
215
- url: url,
216
- tagName: tagName,
217
- isAsyncChunk: false
218
- };
219
- if (typeof config.onRetry === 'function') {
220
- config.onRetry(context1);
221
- }
222
- var _config_delay;
223
- // Delay retry
224
- var delayValue = typeof config.delay === 'function' ? config.delay(context1) : (_config_delay = config.delay) !== null && _config_delay !== void 0 ? _config_delay : 0;
225
- if (delayValue > 0) {
226
- setTimeout(function() {
227
- reloadElementResource(target, element, attributes);
228
- }, delayValue);
229
- } else {
230
- reloadElementResource(target, element, attributes);
231
182
  }
232
- }
233
- function load(config, e) {
234
- var targetInfo = validateTargetInfo(config, e);
235
- if (targetInfo === false) {
236
- return;
237
- }
238
- var target = targetInfo.target, tagName = targetInfo.tagName, url = targetInfo.url;
239
- var domain = findCurrentDomain(url, config.domain);
240
- var retryTimes = Number(target.dataset.rbRetryTimes) || 0;
241
- if (retryTimes === 0) {
242
- return;
243
- }
244
- if (typeof config.onSuccess === 'function') {
245
- var context = {
246
- times: retryTimes,
247
- domain: domain,
248
- url: url,
249
- tagName: tagName,
250
- isAsyncChunk: false
251
- };
252
- config.onSuccess(context);
253
- }
254
- }
255
- function resourceMonitor(error, success) {
256
- if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {
257
- document.addEventListener('error', function(e) {
258
- if (e && _instanceof(e.target, Element)) {
259
- error(e);
260
- }
261
- }, true);
262
- document.addEventListener('load', function(e) {
263
- if (e && _instanceof(e.target, Element)) {
264
- success(e);
265
- }
266
- }, true);
267
- }
268
- }
269
- // init global variables shared with async chunk
270
- if (typeof window !== 'undefined' && !window.__RB_ASYNC_CHUNKS__) {
271
- window.__RB_ASYNC_CHUNKS__ = {};
272
- }
273
- // Bind event in window
274
- try {
275
- var config = __RUNTIME_GLOBALS_OPTIONS__;
276
- resourceMonitor(function(e) {
277
- try {
278
- retry(config, e);
279
- } catch (err) {
280
- console.error('retry error captured', err);
281
- }
282
- }, function(e) {
183
+ function registerInitialChunkRetry() {
184
+ if ('undefined' != typeof window && !window.__RB_ASYNC_CHUNKS__) window.__RB_ASYNC_CHUNKS__ = {};
283
185
  try {
284
- 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
+ }
285
203
  } catch (err) {
286
- console.error('load error captured', err);
204
+ console.error('monitor error captured', err);
287
205
  }
288
- });
289
- } catch (err) {
290
- console.error('monitor error captured', err);
291
- }
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=r.target,o=a.tagName.toLocaleLowerCase(),c=n.type,s=e(i=a,HTMLScriptElement)||e(i,HTMLImageElement)?i.getAttribute("src")?i.src:null:e(i,HTMLLinkElement)?i.getAttribute("href")?i.href:null:null;return!!o&&-1!==c.indexOf(o)&&!!t[o]&&!!e(a,t[o])&&!!s&&{target:a,tagName:o,url:s}}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,b,_,v,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,b=g,_=O,v=w,p.replace(b,_).replace(i,"")+(L=v+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.2",
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
- };