Skip to content

Commit 98a9918

Browse files
authored
fix!: drop sync script retry support and remove document.write for white screen security (#18)
* fix!: remove the document.write for white screen security * chore: update * chore: update
1 parent 98b7f58 commit 98a9918

File tree

5 files changed

+30
-26
lines changed

5 files changed

+30
-26
lines changed

README.md

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ bun add @rsbuild/plugin-assets-retry -D
3737
You can register the plugin in the `rsbuild.config.ts` file:
3838

3939
```ts
40-
import { pluginAssetsRetry } from "@rsbuild/plugin-assets-retry";
40+
import { pluginAssetsRetry } from '@rsbuild/plugin-assets-retry';
4141

4242
export default {
4343
plugins: [pluginAssetsRetry()],
@@ -64,7 +64,7 @@ type AssetsRetryOptions = {
6464
domain?: string[];
6565
max?: number;
6666
test?: string | ((url: string) => boolean);
67-
crossOrigin?: boolean | "anonymous" | "use-credentials";
67+
crossOrigin?: boolean | 'anonymous' | 'use-credentials';
6868
inlineScript?: boolean;
6969
delay?: number | ((context: AssetsRetryHookContext) => number);
7070
onRetry?: (context: AssetsRetryHookContext) => void;
@@ -77,10 +77,10 @@ type AssetsRetryOptions = {
7777

7878
```ts
7979
const defaultAssetsRetryOptions = {
80-
type: ["script", "link", "img"],
80+
type: ['script', 'link', 'img'],
8181
domain: [],
8282
max: 3,
83-
test: "",
83+
test: '',
8484
crossOrigin: false,
8585
delay: 0,
8686
onRetry: () => {},
@@ -103,11 +103,11 @@ For example:
103103
defineConfig({
104104
plugins: [
105105
pluginAssetsRetry({
106-
domain: ["cdn1.com", "cdn2.com", "cdn3.com"],
107-
})
106+
domain: ['cdn1.com', 'cdn2.com', 'cdn3.com'],
107+
}),
108108
],
109109
output: {
110-
assetPrefix: "https://cdn1.com", // or "//cdn1.com"
110+
assetPrefix: 'https://cdn1.com', // or "//cdn1.com"
111111
},
112112
});
113113
```
@@ -127,7 +127,7 @@ For example, only script tags and link tags are processed:
127127

128128
```js
129129
pluginAssetsRetry({
130-
type: ["script", "link"],
130+
type: ['script', 'link'],
131131
});
132132
```
133133

@@ -182,7 +182,7 @@ The callback function when the asset is being retried. For example:
182182
pluginAssetsRetry({
183183
onRetry: ({ times, domain, url, tagName, isAsyncChunk }) => {
184184
console.log(
185-
`Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}, isAsyncChunk: ${isAsyncChunk}`
185+
`Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}, isAsyncChunk: ${isAsyncChunk}`,
186186
);
187187
},
188188
});
@@ -198,7 +198,7 @@ The callback function when the asset is successfully retried. For example:
198198
pluginAssetsRetry({
199199
onSuccess: ({ times, domain, url, tagName, isAsyncChunk }) => {
200200
console.log(
201-
`Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}, isAsyncChunk: ${isAsyncChunk}`
201+
`Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}, isAsyncChunk: ${isAsyncChunk}`,
202202
);
203203
},
204204
});
@@ -214,7 +214,7 @@ The callback function when the asset is failed to be retried. For example:
214214
pluginAssetsRetry({
215215
onFail: ({ times, domain, url, tagName, isAsyncChunk }) => {
216216
console.log(
217-
`Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}, isAsyncChunk: ${isAsyncChunk}`
217+
`Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}, isAsyncChunk: ${isAsyncChunk}`,
218218
);
219219
},
220220
});
@@ -321,7 +321,7 @@ Or pass a function that receives `AssetsRetryHookContext` and returns the delay
321321
```js
322322
// Calculate delay based on retry attempts
323323
pluginAssetsRetry({
324-
delay: (ctx) => (ctx.times + 1) * 1000,
324+
delay: ctx => (ctx.times + 1) * 1000,
325325
});
326326
```
327327

@@ -336,12 +336,12 @@ When you use Assets Retry plugin, the Rsbuild injects some runtime code into the
336336
Here's an example of incorrect usage:
337337

338338
```js
339-
import { someMethod } from "utils";
339+
import { someMethod } from 'utils';
340340

341341
pluginAssetsRetry({
342342
onRetry() {
343343
// Incorrect usage, includes sensitive information
344-
const privateToken = "a-private-token";
344+
const privateToken = 'a-private-token';
345345

346346
// Incorrect usage, uses an external method
347347
someMethod(privateToken);
@@ -353,6 +353,10 @@ pluginAssetsRetry({
353353

354354
Assets Retry plugin may not work in the following scenarios:
355355

356+
### Sync script tag loaded resources
357+
358+
`<script src="..."></script>` tags load resources synchronously, and retrying them does not guarantee the order of resource loading. Therefore, the Assets Retry plugin will not retry resources loaded by synchronous script tags. It will only retry resources loaded by async/defer script tags.
359+
356360
### Module Federation
357361

358362
For remote modules loaded by Module Federation, you can use the [@module-federation/retry-plugin](https://www.npmjs.com/package/@module-federation/retry-plugin) from Module Federation 2.0 to implement static asset retries.

README.zh-CN.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ pluginAssetsRetry({
351351

352352
以下场景 Assets Retry 插件可能无法生效:
353353

354+
### 同步 script 标签加载的资源
355+
356+
`<script src="..."></script>` 标签加载的资源是同步加载的,如果进行重试无法保证资源加载的顺序,因此 Assets Retry 插件不会对同步加载的 script 标签进行重试。只会对 async/defer 的 script 标签进行重试。
357+
354358
### 模块联邦
355359

356360
对于模块联邦加载的远程模块,你可以使用模块联邦 2.0 的 [@module-federation/retry-plugin](https://www.npmjs.com/package/@module-federation/retry-plugin) 来实现静态资源重试。

src/runtime/asyncChunkRetry.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ERROR_PREFIX } from './constants.js';
12
import {
23
findCurrentDomain,
34
findNextDomain,
@@ -174,8 +175,6 @@ const originalGetCssFilename =
174175
(() => null);
175176
const originalLoadScript = __RUNTIME_GLOBALS_LOAD_SCRIPT__;
176177

177-
const ERROR_PREFIX = '[@rsbuild/plugin-assets-retry] ';
178-
179178
// if users want to support es5, add Promise polyfill first https://github.com/webpack/webpack/issues/12877
180179
function ensureChunk(chunkId: string): Promise<unknown> {
181180
// biome-ignore lint/style/noArguments: allowed

src/runtime/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const ERROR_PREFIX = '[@rsbuild/plugin-assets-retry] ';

src/runtime/initialChunkRetry.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// rsbuild/runtime/initial-chunk-retry
2+
import { ERROR_PREFIX } from './constants.js';
23
import {
34
findCurrentDomain,
45
findNextDomain,
@@ -31,18 +32,9 @@ function getRequestUrl(element: HTMLElement) {
3132
element instanceof HTMLScriptElement ||
3233
element instanceof HTMLImageElement
3334
) {
34-
// For <script src="" /> or <img src="" />
35-
// element.getAttribute('src') === '' but element.src === baseURI
36-
if (!element.getAttribute('src')?.trim()) {
37-
return null;
38-
}
3935
return element.src;
4036
}
4137
if (element instanceof HTMLLinkElement) {
42-
// For <link href="" />
43-
if (!element.getAttribute('href')?.trim()) {
44-
return null;
45-
}
4638
return element.href;
4739
}
4840
return null;
@@ -148,7 +140,11 @@ function reloadElementResource(
148140
if (attributes.isAsync) {
149141
document.body.appendChild(fresh.element);
150142
} else {
151-
document.write(fresh.str);
143+
console.warn(
144+
ERROR_PREFIX,
145+
'load sync script failed, for security only async/defer script can be retried',
146+
origin,
147+
);
152148
}
153149
}
154150

0 commit comments

Comments
 (0)