1.2.1 • Published 8 months ago

@rsbuild/plugin-assets-retry v1.2.1

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

@rsbuild/plugin-assets-retry

用于在静态资源加载失败时自动发起重试请求。

快速开始

安装插件

你可以通过如下的命令安装插件:

# npm
npm add @rsbuild/plugin-assets-retry -D

# yarn
yarn add @rsbuild/plugin-assets-retry -D

# pnpm
pnpm add @rsbuild/plugin-assets-retry -D

# bun
bun add @rsbuild/plugin-assets-retry -D

注册插件

你可以在 rsbuild.config.ts 文件中注册插件:

import { pluginAssetsRetry } from "@rsbuild/plugin-assets-retry";

export default {
  plugins: [pluginAssetsRetry()],
};

选项

你可以通过选项来配置资源加载失败时的重试逻辑。

  • 类型:
type AssetsRetryHookContext = {
  times: number;
  domain: string;
  url: string;
  tagName: string;
  isAsyncChunk: boolean;
};

type AssetsRetryOptions = {
  type?: string[];
  domain?: string[];
  max?: number;
  test?: string | ((url: string) => boolean);
  crossOrigin?: boolean | "anonymous" | "use-credentials";
  inlineScript?: boolean;
  delay?: number | ((context: AssetsRetryHookContext) => number);
  onRetry?: (context: AssetsRetryHookContext) => void;
  onSuccess?: (context: AssetsRetryHookContext) => void;
  onFail?: (context: AssetsRetryHookContext) => void;
};
  • 默认值:
const defaultOptions = {
  type: ["script", "link", "img"],
  domain: [],
  max: 3,
  test: "",
  crossOrigin: false,
  delay: 0,
  onRetry: () => {},
  onSuccess: () => {},
  onFail: () => {},
};

domain

  • 类型: string[]
  • 默认值: []

指定资源加载失败时的重试域名列表。在 domain 数组中,第一项是静态资源默认所在的域名,后面几项为备用域名。当某个域名的资源请求失败时,Rsbuild 会在数组中找到该域名,并替换为数组的下一个域名。

比如:

// rsbuild.config.ts
defineConfig({
  plugins: [
    pluginAssetsRetry({
      domain: ["cdn1.com", "cdn2.com", "cdn3.com"],
    })
  ],
  output: {
    assetPrefix: "https://cdn1.com", // 或者 "//cdn1.com"
  },
});

添加以上配置后,当 cdn1.com 域名的资源加载失败时,请求域名会自动降级到 cdn2.com

如果 cdn2.com 的资源也请求失败,则会继续请求 cdn3.com

type

  • 类型: string[]
  • 默认值: ['script', 'link', 'img']

用于指定需要进行重试的 HTML 标签类型。默认会处理 script 标签、link 标签和 img 标签,对应 JS 代码、CSS 代码和图片。

比如只对 script 标签和 link 标签进行处理:

pluginAssetsRetry({
  type: ["script", "link"],
});

max

  • 类型: number
  • 默认值: 3

单个资源的最大重试次数。比如:

pluginAssetsRetry({
  max: 5,
});

test

  • 类型: string | ((url: string) => boolean) | undefined
  • 默认值: undefined

匹配资源 URL 的正则表达式或函数,默认匹配所有资源。比如:

pluginAssetsRetry({
  test: /cdn\.example\.com/,
});

crossOrigin

  • 类型: undefined | boolean | 'anonymous' | 'use-credentials'
  • 默认值: 与 html.crossorigin 一致

在发起资源重新请求时,Rsbuild 会重新创建 <script> 标签,此选项可以设置这些标签的 crossorigin 属性。

默认情况下,crossOrigin 的值会与 html.crossorigin 配置项保持一致,无须额外配置。如果你需要对重新创建的标签进行单独配置,可以使用该选项,比如:

pluginAssetsRetry({
  crossOrigin: true,
});

onRetry

  • 类型: undefined | (context: AssetsRetryHookContext) => void

资源重试时的回调函数。比如:

pluginAssetsRetry({
  onRetry: ({ times, domain, url, tagName, isAsyncChunk }) => {
    console.log(
      `Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}, isAsyncChunk: ${isAsyncChunk}`
    );
  },
});

onSuccess

  • 类型: undefined | (context: AssetsRetryHookContext) => void

资源重试成功时的回调函数。比如:

pluginAssetsRetry({
  onSuccess: ({ times, domain, url, tagName, isAsyncChunk }) => {
    console.log(
      `Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}, isAsyncChunk: ${isAsyncChunk}`
    );
  },
});

onFail

  • 类型: undefined | (context: AssetsRetryHookContext) => void

资源重试超过最大重试次数时的回调函数。比如:

pluginAssetsRetry({
  onFail: ({ times, domain, url, tagName, isAsyncChunk }) => {
    console.log(
      `Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}, isAsyncChunk: ${isAsyncChunk}`
    );
  },
});

addQuery

  • 类型:
type AddQuery =
  | boolean
  | ((context: { times: number; originalQuery: string }) => string);
  • 默认值: false

是否在资源重试时添加 query,这样可以避免被浏览器、CDN 缓存影响到重试的结果。

当设置为 true 时,请求时会在 query 中添加 retry=${times},按照 retry=1retry=2retry=3 依次请求,比如:

  1. 假设请求的静态资源为 https://js.cdn.net/foo.js,请求失败后会自动重试 https://js.cdn.net/foo.js?retry=${times}

  2. 假设请求的静态资源为 https://js.cdn.net/foo.js?version=1,请求失败后会自动重试 https://js.cdn.net/foo.js?version=1&retry=${times}

当你想要自定义 query 时,可以传入一个函数,比如:

  • 示例: 请求的所有资源都不含 query:
pluginAssetsRetry({
  addQuery: ({ times }) => {
    return times === 3
      ? `?retryCount=${times}&isLast=1`
      : `?retryCount=${times}`;
  },
});
  • 示例: 当请求的某些资源中含有 query 时,可以使用 originalQuery 读取:
pluginAssetsRetry({
  addQuery: ({ times, originalQuery }) => {
    const query =
      times === 3 ? `retryCount=${times}&isLast=1` : `retryCount=${times}`;
    return originalQuery ? `${originalQuery}&${query}` : `?${query}`;
  },
});

inlineScript

  • 类型: boolean
  • 默认值: true

是否将 Assets Retry 插件的运行时 JavaScript 代码内联到 HTML 文件中。

如果你不希望在 HTML 文件中插入相关代码,可以将 inlineScript 设置为 false

pluginAssetsRetry({
  inlineScript: false,
});

添加以上配置后,Assets Retry 插件的运行时代码会被抽取为一个独立的 assets-retry.[version].js 文件,并输出到产物目录下。

这种方式的弊端在于,assets-retry.[version].js 自身有加载失败的可能性。如果出现这种情况,静态资源重试的逻辑就无法生效。因此,我们更推荐将运行时代码内联到 HTML 文件中。

minify

  • 类型: boolean
  • 默认值: process.env.NODE_ENV === 'production'

是否对运行时 JavaScript 代码开启代码压缩。

默认情况下,会受到 output.minify 配置的影响。

pluginAssetsRetry({
  minify: true,
});

delay

  • 类型: number | ((context: AssetsRetryHookContext) => number)
  • 默认值: 0

在资源重试前的延迟时间,单位为毫秒。

你可以传入一个数字:

// 延时 1s 重试
pluginAssetsRetry({
  delay: 1000,
});

也可以传入一个函数,函数的参数为 AssetsRetryHookContext,返回值为延迟时间:

// 通过次数来计算延迟时间
pluginAssetsRetry({
  delay: (ctx) => (ctx.times + 1) * 1000,
});

注意事项

当你使用 Assets Retry 插件时,Rsbuild 会分别向 HTML 和 Rspack Runtime 中注入运行时代码,并将 Assets Retry 插件配置的内容序列化后插入到这些代码中,因此你需要注意:

  • 避免在 Assets Retry 插件中配置敏感信息,比如内部使用的 token。
  • 避免在 onRetryonSuccessonFail 中引用函数外部的变量或方法。
  • 避免在 onRetryonSuccessonFail 中使用有兼容性问题的语法,因为这些函数会被直接内联到 HTML 中。

以下是一个错误示例:

import { someMethod } from "utils";

pluginAssetsRetry({
  onRetry() {
    // 错误用法,包含了敏感信息
    const privateToken = "a-private-token";

    // 错误用法,使用了外部的方法
    someMethod(privateToken);
  },
});

使用限制

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

模块联邦

对于模块联邦加载的远程模块,你可以使用模块联邦 2.0 的 @module-federation/retry-plugin 来实现静态资源重试。

微前端

如果你的工程是微前端应用(比如 Garfish 子应用),那么 Assets Retry 插件可能无法生效,因为微前端子应用通常不是基于 <script> 标签直接加载的。

如果你需要对微前端场景的资源加载进行重试,请联系微前端框架的开发者,以寻找相应的解决方案。

自定义模版中的资源

Assets Retry 插件通过监听页面 error 事件来获悉当前资源是否加载失败需要重试。因此,如果自定义模版中的资源执行早于 Assets Retry 插件,那 Assets Retry 插件无法监听到该资源加载失败的事件,retry 无法对其生效。

如果想要 Assets Retry 插件对自定义模版中的资源生效,可参考 自定义插入示例 来修改 html.inject 配置和自定义模版。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>custom template</title>
+   <%= htmlPlugin.tags.headTags %>
    <script src="https://example.com/assets/a.js"></script>
  </head>
  <body>
    <div id="root" />
+    <%= htmlPlugin.tags.bodyTags %>
  </body>
</html>

License

MIT.

1.2.0

8 months ago

1.2.1

8 months ago

1.1.0-beta.0

10 months ago

1.1.1

8 months ago

1.1.0

9 months ago

1.0.7

11 months ago

1.0.6

11 months ago

1.0.5

11 months ago

1.0.4

12 months ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.1-rc.5

1 year ago

1.0.1-rc.4

1 year ago

1.0.1-rc.3

1 year ago

1.0.1-rc.1

1 year ago

1.0.1-rc.2

1 year ago

1.0.1-rc.0

1 year ago

1.0.0-alpha.9

1 year ago

1.0.0-alpha.8

1 year ago

1.0.0-alpha.7

1 year ago

1.0.0-alpha.6

1 year ago

1.0.0-alpha.5

1 year ago

1.0.0-alpha.4

1 year ago

1.0.0-alpha.3

1 year ago

1.0.0-alpha.2

1 year ago

1.0.0-alpha.1

1 year ago

1.0.0-alpha.0

1 year ago

0.7.2

1 year ago

0.7.1

1 year ago

0.7.4

1 year ago

0.7.3

1 year ago

0.7.0

1 year ago

0.7.10

1 year ago

0.7.0-beta.8

1 year ago

0.7.0-beta.9

1 year ago

0.7.0-beta.7

1 year ago

0.7.9

1 year ago

0.7.6

1 year ago

0.7.5

1 year ago

0.7.8

1 year ago

0.7.7

1 year ago

1.0.1-beta.2

1 year ago

1.0.1-beta.1

1 year ago

1.0.1-beta.0

1 year ago

1.0.1-beta.6

1 year ago

1.0.1-beta.5

1 year ago

1.0.1-beta.4

1 year ago

1.0.1-beta.3

1 year ago

1.0.1-beta.9

1 year ago

1.0.1-beta.8

1 year ago

1.0.1-beta.7

1 year ago

1.0.1-beta.10

1 year ago

1.0.1-beta.11

1 year ago

1.0.1-beta.14

1 year ago

1.0.1-beta.15

1 year ago

1.0.1-beta.12

1 year ago

1.0.1-beta.13

1 year ago

1.0.1-beta.16

1 year ago

0.7.0-beta.6

1 year ago

0.7.0-beta.5

1 year ago

0.7.0-beta.4

1 year ago

0.7.0-beta.1

1 year ago

0.7.0-beta.2

1 year ago

0.7.0-beta.3

1 year ago

0.7.0-beta.0

1 year ago

0.6.15

1 year ago

0.6.14

1 year ago

0.6.12

1 year ago

0.6.13

1 year ago

0.6.10

1 year ago

0.6.11

1 year ago

0.6.9

1 year ago

0.6.8

2 years ago

0.6.7

2 years ago

0.6.6

2 years ago

0.6.5

2 years ago

0.6.4

2 years ago

0.6.3

2 years ago

0.6.2

2 years ago

0.6.1

2 years ago

0.6.0

2 years ago

0.5.8

2 years ago

0.5.9

2 years ago

0.5.7

2 years ago

0.5.6

2 years ago

0.5.5

2 years ago

0.5.4

2 years ago

0.5.3

2 years ago

0.5.2

2 years ago

0.5.0

2 years ago

0.5.1

2 years ago

0.4.15

2 years ago

0.4.14

2 years ago

0.4.13

2 years ago

0.4.12

2 years ago

0.4.11

2 years ago

0.4.10

2 years ago

0.4.9

2 years ago

0.4.8

2 years ago

0.4.7

2 years ago

0.4.5

2 years ago

0.4.6

2 years ago

0.4.4

2 years ago

0.4.3

2 years ago

0.4.2

2 years ago

0.4.1

2 years ago

0.4.0

2 years ago

0.3.11

2 years ago

0.3.10

2 years ago

0.3.8

2 years ago

0.3.9

2 years ago

0.3.7

2 years ago

0.3.6

2 years ago

0.3.5

2 years ago

0.3.4

2 years ago

0.3.3

2 years ago

0.3.2

2 years ago

0.3.1

2 years ago

0.3.0

2 years ago

0.2.18

2 years ago

0.2.17

2 years ago

0.2.16

2 years ago

0.2.15

2 years ago

0.2.14

2 years ago

0.2.13

2 years ago

0.2.12

2 years ago

0.2.11

2 years ago

0.2.10

2 years ago

0.2.9

2 years ago

0.2.8

2 years ago

0.2.7

2 years ago

0.2.6

2 years ago

0.2.5

2 years ago

0.2.4

2 years ago

0.2.3

2 years ago

0.2.1

2 years ago

0.2.0

2 years ago

0.2.2

2 years ago

0.1.9

2 years ago

0.1.8

2 years ago

0.1.7

2 years ago

0.1.6

2 years ago

0.1.5

2 years ago

0.1.4

2 years ago

0.1.3

2 years ago

0.1.2

2 years ago

0.1.1

2 years ago

0.1.0

2 years ago

1.0.0

2 years ago

0.0.28

2 years ago

0.0.27

2 years ago

0.0.26

2 years ago

0.0.25

2 years ago

0.0.24

2 years ago

0.0.23

2 years ago

0.0.22

2 years ago

0.0.21

2 years ago

0.0.20

2 years ago

0.0.19

2 years ago

0.0.18

2 years ago