Skip to content

Commit

Permalink
docs: add SubresourceIntegrityPlugin (#9302)
Browse files Browse the repository at this point in the history
docs: add sri plugin
  • Loading branch information
LingyuCoder authored Feb 14, 2025
1 parent b8488a5 commit 4c2aec8
Show file tree
Hide file tree
Showing 3 changed files with 375 additions and 2 deletions.
3 changes: 1 addition & 2 deletions packages/rspack/scripts/check-documentation-coverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ function checkPluginsDocumentationCoverage() {
const excludedPlugins = [
"OriginEntryPlugin",
"RuntimePlugin", // This plugin only provides hooks, should not be used separately
"RsdoctorPlugin", // This plugin is not stable yet
"SubresourceIntegrityPlugin" // TODO: add document in next pr
"RsdoctorPlugin" // This plugin is not stable yet
];

const undocumentedPlugins = Array.from(implementedPlugins).filter(
Expand Down
189 changes: 189 additions & 0 deletions website/docs/en/plugins/rspack/subresource-integrity-plugin.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { ApiMeta } from '@components/ApiMeta.tsx';

# SubresourceIntegrityPlugin

<ApiMeta specific={['Rspack']} addedVersion="1.2.4" />

The `rspack.experiments.SubresourceIntegrityPlugin` is a plugin for enabling Subresource Integrity in Rspack.

## What is SRI

Subresource Integrity (SRI) is a security feature that enables browsers to verify that resources they fetch (for example, from a CDN) are delivered without unexpected manipulation. It works by allowing you to provide a cryptographic hash that a fetched resource must match.

For `<script>` tags, the result is to refuse to execute the code; for CSS links, the result is not to load the styles.

For more on subresource integrity, see [Subresource Integrity - MDN](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity).

## Features

### Support for HTML Plugin

The plugin supports integration with [`HtmlRspackPlugin`](/plugins/rspack/html-rspack-plugin) and [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin). It will automatically set the `integrity` and `crossorigin` attributes for the injected tags.

### Support for Code Splitting

The plugin supports code splitting. When you use dynamic imports, the plugin will automatically set the `integrity` and `crossorigin` attributes for the generated chunk loading tags.

## Usage

You can use the plugin by importing it as an experimental plugin from `@rspack/core`:

```js title="rspack.config.mjs"
import { experiments } from '@rspack/core';
const { SubresourceIntegrityPlugin } = experiments;
```

Or:

```js title="rspack.config.cjs"
const {
experiments: { SubresourceIntegrityPlugin },
} = require('@rspack/core');
```

### Recommended Rspack Configuration

The [output.crossOriginLoading](/config/output#outputcrossoriginloading) option is required for SRI to work:

```js title="rspack.config.mjs"
import { experiments: { SubresourceIntegrityPlugin } } from "@rspack/core";

export default {
output: {
crossOriginLoading: "anonymous",
},
plugins: [new SubresourceIntegrityPlugin()],
};
```

### With HTML Plugin

When the HTML plugin([`HtmlRspackPlugin`](/plugins/rspack/html-rspack-plugin.mdx) or [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin)) is used, the `integrity` and `crossorigin` attributes will be set automatically.

The SubresourceIntegrityPlugin will interact with [`HtmlRspackPlugin`](/plugins/rspack/html-rspack-plugin.mdx) by default:

```js title="rspack.config.mjs"
import { experiments: { SubresourceIntegrityPlugin }, HtmlRspackPlugin } from "@rspack/core";

export default {
plugins: [
new SubresourceIntegrityPlugin(),
new HtmlRspackPlugin()
],
};
```

If [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin) is used, the `htmlPlugin` option should be specified to the path of it:

```js title="rspack.config.mjs"
import { experiments: { SubresourceIntegrityPlugin } } from "@rspack/core";
import HtmlWebpackPlugin from "html-webpack-plugin";

export default {
plugins: [
new SubresourceIntegrityPlugin({
// the path to the html-webpack-plugin
htmlPlugin: import.meta.resolve("html-webpack-plugin"),
}),
new HtmlWebpackPlugin()
],
};
```

### With HTML Plugin and `inject: false`

If you use the HTML plugin with `inject: false`, you need to set the `integrity` and `crossorigin` attributes in your template manually.

With [`HtmlRspackPlugin`](/plugins/rspack/html-rspack-plugin.mdx), the grammar of the template is a bit different with `.ejs`(see [here](/plugins/rspack/html-rspack-plugin#supported-ejs-syntax)), you can inject them like this:

```ejs title="index.ejs"
<% for src in htmlRspackPlugin.files.js { %>
<script src="<%= src %>"
integrity="<%= htmlRspackPlugin.files.jsIntegrity[index] %>"
crossorigin="<%= rspackConfig.output.crossOriginLoading %>"
></script>
<% } %>
<% for _ in htmlRspackPlugin.files.css { %>
<link href="<%= htmlRspackPlugin.files.css[index] %>"
integrity="<%= htmlRspackPlugin.files.cssIntegrity[index] %>"
crossorigin="<%= rspackConfig.output.crossOriginLoading %>"
rel="stylesheet"
/>
<% } %>
```

With [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin), you can inject them like this:

```ejs title="index.ejs"
<% for (let index in htmlWebpackPlugin.files.js) { %>
<script
src="<%= htmlWebpackPlugin.files.js[index] %>"
integrity="<%= htmlWebpackPlugin.files.jsIntegrity[index] %>"
crossorigin="<%= webpackConfig.output.crossOriginLoading %>"
></script>
<% } %>
<% for (let index in htmlWebpackPlugin.files.css) { %>
<link
rel="stylesheet"
href="<%= htmlWebpackPlugin.files.css[index] %>"
integrity="<%= htmlWebpackPlugin.files.cssIntegrity[index] %>"
crossorigin="<%= webpackConfig.output.crossOriginLoading %>"
/>
<% } %>
```

### Without HTML Plugin

The `integrity` can also be obtained from `stats.assets`. For example:

```js
compiler.plugin('done', stats => {
const integrityValues = stats
.toJson()
.assets.map(asset => [asset.name, asset.integrity]);
});
```

:::tip
Note that when you add the `integrity` attribute on your `link` and
`script` tags, you're also required to set the `crossorigin`
attribute. It is recommended to set this attribute to the same value
as the Rspack `output.crossOriginLoading` configuration option.
:::

## Options

#### hashFuncNames

- **Type:** `Array<"sha256" | "sha384" | "sha512">`
- **Default:** `["sha384"]`

An array of strings, each specifying the name of a hash function to be
used for calculating integrity hash values. Only supports `sha256`, `sha384`, and `sha512` yet.

> See [SRI: Cryptographic hash functions](http://www.w3.org/TR/SRI/#cryptographic-hash-functions) for more details.
#### enabled

- **Type:** `"auto" | boolean`
- **Default:** `"auto"`

- `auto` is the default value, which means the plugin is enabled when [Rspack mode](/config/mode) is `production` or `none`, and disabled when it is `development`.
- `true` means the plugin is enabled in any mode.
- `false` means the plugin is disabled in any mode.

#### htmlPlugin

- **Type:** `string`
- **Default:** `"HtmlRspackPlugin"`

The path to the HTML plugin, defaults to `"HtmlRspackPlugin"` which means the native HTML plugin of Rspack. If you are using the `html-webpack-plugin`, you can set this option to the path of it. It is recommended to set the absolute path to make sure the plugin can be found.

## More Information

You can find more information about Subresource Integrity in the following resources:

- [webpack-subresource-integrity](https://github.com/waysact/webpack-subresource-integrity/blob/main/webpack-subresource-integrity/README.md)
- [MDN: Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)
185 changes: 185 additions & 0 deletions website/docs/zh/plugins/rspack/subresource-integrity-plugin.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import { ApiMeta } from '@components/ApiMeta.tsx';

# SubresourceIntegrityPlugin

<ApiMeta specific={['Rspack']} addedVersion="1.2.4" />

`rspack.experiments.SubresourceIntegrityPlugin` 是一个用于在 Rspack 中启用子资源完整性的插件。

## 什么是 SRI

子资源完整性 Subresource Integrity(SRI)是专门用来校验资源的一种方案,它读取资源标签中的 integrity 属性,将其中的信息摘要值,和资源实际的信息摘要值进行对比,如果发现无法匹配,那么浏览器就会拒绝执行资源。

对于 `<script>` 标签来说,结果为拒绝执行其中的代码;对于 CSS links 来说,结果为不加载其中的样式。

关于 SRI 的更多内容,可以查看 [Subresource Integrity - MDN](https://developer.mozilla.org/zh-CN/docs/Web/Security/Subresource_Integrity)

## 特性

### 支持 HTML 插件

支持与 [`HtmlRspackPlugin`](/plugins/rspack/html-rspack-plugin)[`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin) 集成。它会自动为注入的标签设置 `integrity``crossorigin` 属性。

### 支持代码分割

该插件支持代码分割。使用动态导入时,插件会在生成加载 chunk 的标签时自动设置 `integrity``crossorigin` 属性。

## 使用方法

可以通过从 `@rspack/core` 中导入,目前该插件处于实验性阶段:

```js title="rspack.config.mjs"
import { experiments } from '@rspack/core';
const { SubresourceIntegrityPlugin } = experiments;
```


```js title="rspack.config.cjs"
const {
experiments: { SubresourceIntegrityPlugin },
} = require('@rspack/core');
```

### 推荐的 Rspack 配置

为了确保 SRI 正常工作,需要配置 [output.crossOriginLoading](/config/output#outputcrossoriginloading) 选项:

```js title="rspack.config.mjs"
import { experiments: { SubresourceIntegrityPlugin } } from "@rspack/core";

export default {
output: {
crossOriginLoading: "anonymous",
},
plugins: [new SubresourceIntegrityPlugin()],
};
```

### 使用 HTML 插件

当使用 HTML 插件([`HtmlRspackPlugin`](/plugins/rspack/html-rspack-plugin.mdx)[`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin))时,`integrity``crossorigin` 属性将被自动设置。

SubresourceIntegrityPlugin 默认会与 [`HtmlRspackPlugin`](/plugins/rspack/html-rspack-plugin.mdx) 交互:

```js title="rspack.config.mjs"
import { experiments: { SubresourceIntegrityPlugin }, HtmlRspackPlugin } from "@rspack/core";

export default {
plugins: [
new SubresourceIntegrityPlugin(),
new HtmlRspackPlugin()
],
};
```

如果使用 [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin),需要在 `htmlPlugin` 选项中指定其路径:

```js title="rspack.config.mjs"
import { experiments: { SubresourceIntegrityPlugin } } from "@rspack/core";
import HtmlWebpackPlugin from "html-webpack-plugin";

export default {
plugins: [
new SubresourceIntegrityPlugin({
// html-webpack-plugin 的路径
htmlPlugin: import.meta.resolve("html-webpack-plugin"),
}),
new HtmlWebpackPlugin()
],
};
```

### 使用 HTML 插件并且 `inject: false`

如果使用 HTML 插件时设置了 `inject: false`,你需要在模板中手动注入 `integrity``crossorigin` 属性。

对于 [`HtmlRspackPlugin`](/plugins/rspack/html-rspack-plugin.mdx),模板的语法与标准 `.ejs` 稍有不同不同(参考[文档](/plugins/rspack/html-rspack-plugin#supported-ejs-syntax)),可以这样注入属性:

```ejs title="index.ejs"
<% for in htmlRspackPlugin.files.js { %>
<script src="<%= htmlRspackPlugin.files.js[index] %>"
integrity="<%= htmlRspackPlugin.files.jsIntegrity[index] %>"
crossorigin="<%= rspackConfig.output.crossOriginLoading %>"
></script>
<% } %>
<% for _ in htmlRspackPlugin.files.css { %>
<link href="<%= htmlRspackPlugin.files.css[index] %>"
integrity="<%= htmlRspackPlugin.files.cssIntegrity[index] %>"
crossorigin="<%= rspackConfig.output.crossOriginLoading %>"
rel="stylesheet"
/>
<% } %>
```

对于 [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin),可以这样注入属性:

```ejs title="index.ejs"
<% for (let index in htmlWebpackPlugin.files.js) { %>
<script
src="<%= htmlWebpackPlugin.files.js[index] %>"
integrity="<%= htmlWebpackPlugin.files.jsIntegrity[index] %>"
crossorigin="<%= webpackConfig.output.crossOriginLoading %>"
></script>
<% } %>
<% for (let index in htmlWebpackPlugin.files.css) { %>
<link
rel="stylesheet"
href="<%= htmlWebpackPlugin.files.css[index] %>"
integrity="<%= htmlWebpackPlugin.files.cssIntegrity[index] %>"
crossorigin="<%= webpackConfig.output.crossOriginLoading %>"
/>
<% } %>
```

### 不使用 HTML 插件

若不使用 HTML 插件,也可以从 `stats.assets` 中获取 `integrity` 属性,如:

```js
compiler.plugin('done', stats => {
const integrityValues = stats
.toJson()
.assets.map(asset => [asset.name, asset.integrity]);
});
```

:::tip 提示
当你在 `link``script` 标签上添加 `integrity` 属性时,你还需要设置 `crossorigin` 属性。建议将此属性设置为与 Rspack 的 `output.crossOriginLoading` 配置选项相同的值。
:::

## 选项

#### hashFuncNames

- **类型:** `Array<"sha256" | "sha384" | "sha512">`
- **默认值:** `["sha384"]`

一个字符串数组,每个字符串指定用于计算完整性哈希值的哈希函数的名称。目前仅支持 `sha256``sha384``sha512`

> 更多详情请参见 [SRI:加密哈希函数](http://www.w3.org/TR/SRI/#cryptographic-hash-functions)
#### enabled

- **类型:** `"auto" | boolean`
- **默认值:** `"auto"`

- `auto` 是默认值,表示在 [Rspack mode](/config/mode)`production``none` 时启用插件,在 `development` 时禁用插件。
- `true` 表示在任意 mode 下都启用插件。
- `false` 表示在任意 mode 下都不启用插件。

#### htmlPlugin

- **类型:** `string`
- **默认值:** `"HtmlRspackPlugin"`

HTML 插件的路径,默认为 `"HtmlRspackPlugin"`,表示 Rspack 的原生 HTML 插件。如果你使用的是 [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin),你可以将此选项设置为它的路径。建议设置绝对路径以确保能找到正确的插件实例。

## 更多信息

更多关于子资源完整性的信息可参考:

- [webpack-subresource-integrity](https://github.com/waysact/webpack-subresource-integrity/blob/main/webpack-subresource-integrity/README.md)
- [MDN:子资源完整性](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)

2 comments on commit 4c2aec8

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented on 4c2aec8 Feb 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Benchmark detail: Open

Name Base (2025-02-14 05524cd) Current Change
10000_big_production-mode_disable-minimize + exec 37.9 s ± 263 ms 40.1 s ± 973 ms +5.95 %
10000_development-mode + exec 1.83 s ± 21 ms 1.86 s ± 11 ms +1.33 %
10000_development-mode_hmr + exec 680 ms ± 7.1 ms 687 ms ± 2.8 ms +0.98 %
10000_production-mode + exec 2.29 s ± 68 ms 2.36 s ± 195 ms +3.11 %
10000_production-mode_persistent-cold + exec 2.44 s ± 66 ms 2.5 s ± 138 ms +2.64 %
10000_production-mode_persistent-hot + exec 1.68 s ± 135 ms 1.67 s ± 44 ms -0.78 %
arco-pro_development-mode + exec 1.8 s ± 164 ms 1.78 s ± 134 ms -0.90 %
arco-pro_development-mode_hmr + exec 388 ms ± 1.9 ms 388 ms ± 2.7 ms +0.11 %
arco-pro_production-mode + exec 3.6 s ± 123 ms 3.71 s ± 179 ms +2.94 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.63 s ± 134 ms 3.72 s ± 173 ms +2.46 %
arco-pro_production-mode_persistent-cold + exec 3.79 s ± 176 ms 3.89 s ± 426 ms +2.78 %
arco-pro_production-mode_persistent-hot + exec 2.37 s ± 75 ms 2.38 s ± 105 ms +0.50 %
arco-pro_production-mode_traverse-chunk-modules + exec 3.62 s ± 183 ms 3.75 s ± 267 ms +3.48 %
large-dyn-imports_development-mode + exec 2.12 s ± 18 ms 2.13 s ± 74 ms +0.53 %
large-dyn-imports_production-mode + exec 2.15 s ± 48 ms 2.18 s ± 41 ms +1.36 %
threejs_development-mode_10x + exec 1.58 s ± 69 ms 1.55 s ± 33 ms -1.81 %
threejs_development-mode_10x_hmr + exec 785 ms ± 7.9 ms 777 ms ± 22 ms -1.03 %
threejs_production-mode_10x + exec 5.25 s ± 50 ms 5.3 s ± 369 ms +1.04 %
threejs_production-mode_10x_persistent-cold + exec 5.31 s ± 95 ms 5.39 s ± 362 ms +1.53 %
threejs_production-mode_10x_persistent-hot + exec 4.52 s ± 102 ms 4.55 s ± 295 ms +0.59 %
10000_big_production-mode_disable-minimize + rss memory 8704 MiB ± 49.5 MiB 8700 MiB ± 84 MiB -0.04 %
10000_development-mode + rss memory 636 MiB ± 27.9 MiB 643 MiB ± 13 MiB +1.08 %
10000_development-mode_hmr + rss memory 1223 MiB ± 158 MiB 1276 MiB ± 225 MiB +4.33 %
10000_production-mode + rss memory 628 MiB ± 14.1 MiB 625 MiB ± 20.5 MiB -0.55 %
10000_production-mode_persistent-cold + rss memory 735 MiB ± 12.5 MiB 736 MiB ± 17.4 MiB +0.16 %
10000_production-mode_persistent-hot + rss memory 719 MiB ± 3.87 MiB 722 MiB ± 15.3 MiB +0.43 %
arco-pro_development-mode + rss memory 583 MiB ± 24.4 MiB 575 MiB ± 22.6 MiB -1.42 %
arco-pro_development-mode_hmr + rss memory 644 MiB ± 77 MiB 645 MiB ± 89.8 MiB +0.15 %
arco-pro_production-mode + rss memory 724 MiB ± 7.62 MiB 714 MiB ± 32.6 MiB -1.42 %
arco-pro_production-mode_generate-package-json-webpack-plugin + rss memory 728 MiB ± 15.8 MiB 736 MiB ± 32.2 MiB +1.05 %
arco-pro_production-mode_persistent-cold + rss memory 843 MiB ± 21.6 MiB 835 MiB ± 38.9 MiB -0.98 %
arco-pro_production-mode_persistent-hot + rss memory 710 MiB ± 22.1 MiB 713 MiB ± 32.9 MiB +0.42 %
arco-pro_production-mode_traverse-chunk-modules + rss memory 709 MiB ± 8.18 MiB 718 MiB ± 36.3 MiB +1.25 %
large-dyn-imports_development-mode + rss memory 643 MiB ± 3.77 MiB 642 MiB ± 6.8 MiB -0.17 %
large-dyn-imports_production-mode + rss memory 525 MiB ± 6.6 MiB 526 MiB ± 4.86 MiB +0.17 %
threejs_development-mode_10x + rss memory 552 MiB ± 18.3 MiB 556 MiB ± 19.7 MiB +0.72 %
threejs_development-mode_10x_hmr + rss memory 1105 MiB ± 90.1 MiB 1154 MiB ± 134 MiB +4.40 %
threejs_production-mode_10x + rss memory 841 MiB ± 33 MiB 841 MiB ± 24.8 MiB 0.00 %
threejs_production-mode_10x_persistent-cold + rss memory 968 MiB ± 36.3 MiB 968 MiB ± 50.5 MiB -0.03 %
threejs_production-mode_10x_persistent-hot + rss memory 866 MiB ± 43.1 MiB 871 MiB ± 47.9 MiB +0.56 %

Threshold exceeded: ["10000_big_production-mode_disable-minimize + exec"]

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented on 4c2aec8 Feb 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Ecosystem CI detail: Open

suite result
modernjs ✅ success
rspress ✅ success
rslib ✅ success
rsbuild ❌ failure
rsdoctor ❌ failure
examples ✅ success
devserver ✅ success
nuxt ✅ success

Please sign in to comment.