webpack 5 如何用 output.html.csp 为内联脚本与样式生成带哈希的 CSP meta 标签

发布时间:2026/9/10 5:59:09
webpack 5 如何用 output.html.csp 为内联脚本与样式生成带哈希的 CSP meta 标签 webpack 5 如何用 output.html.csp 为内联脚本与样式生成带哈希的 CSP meta 标签【免费下载链接】webpackA bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through loaders, modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.项目地址: https://gitcode.com/GitHub_Trending/web/webpack如果你的 webpack 构建会产出 HTML 页面而你想在页面上启用 Content-Security-Policy又不想维护第三方 CSP 插件webpack 5 的实验性 HTML 模块支持experiments.html提供了output.html.csp选项它在每个 webpack 产出的 HTML 页面中注入一个meta http-equivContent-Security-Policy标签并为页面上每一个内联script/style附上sha256哈希。本文基于仓库中的 html-csp 示例 和 WebpackOptions.json 中该字段的定义走一遍从配置到验证的完整路径。前提条件均来自上述文档使用 webpack 5并启用实验性 HTML 模块experiments: { html: true }。output.html.csp默认为false什么都不做只有显式配置后才会生效。CSP 哈希是在内联之后计算的因此每个哈希与浏览器实际执行的字节一一对应这也是为什么通常需要配合output.html.inline一起使用。准备示例文件仓库中的 examples/html-csp 给出了完整的可复现工程。页面结构是一个入口 HTML 加上外部引用的脚本和样式以及一个原本就写在 HTML 里的内联样式入口 src/index.html!DOCTYPE html html langen head meta charsetutf-8 / titleCSP/title !-- 外部样式表被打包后由 output.html.inline 内联成 style从而被 CSP 哈希 -- link relstylesheet href./styles.css / !-- 内联 style原样被哈希 -- style body { font-family: sans-serif; } /style /head body h1Content-Security-Policy/h1 !-- 外部脚本被打包后内联成 script 并被哈希 -- script src./app.js/script /body /html另外两个模块文件// src/app.js document.querySelector(h1).classList.add(ready); console.log(bundled inlined script, covered by a CSP hash);/* src/styles.css */ h1 { color: #2b3a42; } h1.ready { color: #8ed6fb; }配置 webpack.config.js关键是output.html下的两个选项配合完整文件见 examples/html-csp/webpack.config.jsuse strict; /** type {import(../../).Configuration} */ module.exports { entry: { index: ./src/index.html }, output: { html: { // 把每个产出的 chunk 内联进页面产生供 CSP 哈希的内联 script/style // script/style 或 RegExp 数组可以收窄内联范围未内联的部分由 self 覆盖 inline: true, // true 严格基线script-src/style-src self、object-src none、base-uri self // 外加每个内联脚本/样式一个 sha256传对象可以加 nonce 或通过 policy 覆盖指令 csp: true } }, experiments: { html: true } };两个选项的作用依据 WebpackOptions.json 的字段描述与示例 READMEinline: true把每个产出的 chunk 直接内联进 HTML而不是输出单独的script src/link relstylesheet标签。这样原本外部的link relstylesheet和script src会变成内联的style/script与源文件中本来就内联的标签一起成为可哈希对象。inline的其他取值script只内联 JavaScriptstyle只内联 CSS传入RegExp数组则按 chunk 名匹配。csp: true注入 CSPmeta基线为script-src self、style-src self、object-src none、base-uri self并把每个内联script/style的sha256哈希追加到script-src/style-src。哈希在内联完成后计算因此与浏览器实际执行的字节一致仍然留在页面外部的资源由self覆盖。在这个示例目录下用 webpack CLI 运行一次构建配置即上面这份即可产出dist/index.html。验证产出页面构建成功后webpack 输出compiled successfully检查dist/index.html。文档示例的产出页面开头如下摘自 examples/html-csp/README.md其中的哈希值是文档示例!DOCTYPE html html langen headmeta http-equivContent-Security-Policy contentscript-src self sha256-5NlCGoSN8ETSUabbmQKYTt1H6nvYWb5OGZJTsWS8iC8; style-src self sha256-vp73KxgWfPhtZ9IRKOt378FrPIkD/T6FbLXnXfaktI8 sha256-Ver9ZPpEiV0Cq4WfPc7DLLUo1ECenMRe/8IigOwA; object-src none; base-uri self meta charsetutf-8 / titleCSP/title !-- 外部样式表被打包后由 output.html.inline 内联成 style从而被 CSP 哈希 -- style/*! ... ***! h1 { color: #2b3a42; } h1.ready { color: #8ed6fb; } /style !-- 内联 style原样被哈希 -- style/*! ... ***! body { font-family: sans-serif; } /style /head body h1Content-Security-Policy/h1 !-- 外部脚本被打包后内联成 script 并被哈希 -- script/******/ (() { // webpackBootstrap /*! ... ***! document.querySelector(h1).classList.add(ready); console.log(bundled inlined script, covered by a CSP hash); /******/ })() ;/script /body /html验证要点页面head中出现生成的meta http-equivContent-Security-Policystyle-src中出现了两个哈希对应内联后的外部样式表 源文件中原本就内联的stylescript-src中出现一个哈希对应内联后的app.jsbundle每个内联script/style都能在该 meta 中找到对应的哈希条目。由于哈希按内联后的字节计算页面内容任何变动都会使旧哈希失配。README 中还给出了该示例在 Unoptimized 与 Production mode 下两次构建的 stats 输出同样为文档示例可用于核对编译是否成功以及哪些资产被产出。可选分支nonce 与自定义 policy把csp: true改为对象即可定制字段定义见 WebpackOptions.json 中output.html.csp的描述hashFunction内联script/style的哈希算法可选sha256、sha384、sha512nonce占位 nonce会加到注入的script/style标签上并作为nonce-…源写入策略。注意它是占位符需要服务端在每次请求时重写rewrite it per request server-sidepolicy在基线之上合并的 CSP 指令键是指令名如img-src值是单个 source 字符串或 source 数组。内联哈希和nonce仍然会被追加到script-src/style-src。示例来自 READMEoutput: { html: { inline: true, csp: { policy: { img-src: [self, data:] } } } }已知限制该功能依附于实验性HTML 模块支持experiments.html不是稳定的通用入口output.html.inline在 schema 中标注为 5.109.0 加入。页面中已声明的 CSP 不会被触碰schema 描述明确“Skipped when the page already declares a CSP”即作者自己在页面里写好的 CSP meta 优先webpack 跳过注入。只有被内联的脚本/样式才会获得哈希仍以外链形式存在的资源依赖基线中的self如果你的页面需要从其他域加载脚本或样式需要通过policy显式扩展对应指令。该机制不依赖任何 CSP 插件全部由 webpack 在产出 HTML 时完成。完成配置与验证后产出页面上就会带有与内联内容逐字节对应的 CSP meta 标签若后续需要按请求下发真实 nonce按上面nonce字段说明在服务端做替换即可。【免费下载链接】webpackA bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through loaders, modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.项目地址: https://gitcode.com/GitHub_Trending/web/webpack创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考