SubresourceIntegrityPlugin

Added in v1.2.4Rspack only

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

什么是 SRI

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

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

关于 SRI 的更多内容,可以查看 Subresource Integrity - MDN

特性

支持 HTML 插件

支持与 HtmlRspackPluginhtml-webpack-plugin 集成。它会自动为注入的标签设置 integritycrossorigin 属性。

支持代码分割

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

使用方法

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

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

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

推荐的 Rspack 配置

为了确保 SRI 正常工作,需要配置 output.crossOriginLoading 选项:

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

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

使用 HTML 插件

当使用 HTML 插件(HtmlRspackPluginhtml-webpack-plugin)时,integritycrossorigin 属性将被自动设置。

SubresourceIntegrityPlugin 默认会与 HtmlRspackPlugin 交互:

rspack.config.mjs
import { experiments, HtmlRspackPlugin } from '@rspack/core';
const { SubresourceIntegrityPlugin } = experiments;

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

如果使用 html-webpack-plugin,需要在 htmlPlugin 选项中指定其路径:

rspack.config.mjs
import HtmlWebpackPlugin from 'html-webpack-plugin';
import { experiments } from '@rspack/core';
const { SubresourceIntegrityPlugin } = experiments;

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

使用 HTML 插件并且 inject: false

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

对于 HtmlRspackPlugin,模板的语法与标准 .ejs 稍有不同不同(参考文档),可以这样注入属性:

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,可以这样注入属性:

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 属性,如:

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

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

选项

hashFuncNames

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

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

更多详情请参见 SRI:加密哈希函数

enabled

  • 类型: "auto" | boolean

  • 默认值: "auto"

  • auto 是默认值,表示在 Rspack modeproductionnone 时启用插件,在 development 时禁用插件。

  • true 表示在任意 mode 下都启用插件。

  • false 表示在任意 mode 下都不启用插件。

htmlPlugin

  • 类型: string
  • 默认值: "HtmlRspackPlugin"

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

更多信息

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