为什么 CSP script-src unsafe-inline 会在我的 Angular webapp 上引发样式问题?

Why does CSP script-src unsafe-inline induce styling issues on my Angular webapp?

问题:

当我尝试删除 script-src CSP 的 unsafe-inline 源时,我的 Angular webapp 不再工作。

此问题的根本原因是什么?

在Angular@12+中使用SCSS时,Angular在index.html

上添加一个属性onload

<link rel="stylesheet" href="styles.672c1ac3d6da8cc311a2.css" media="print" onload="this.media='all'">

这会导致违反 script-src header 的 CSP unsafe-inline 来源。

如何解决此问题并在我的 Angular 网络应用程序中删除此“安全漏洞”?

解决方法:

"inlineCritical": false 添加到 angular.json 解决了问题,因为它禁用了关键 CSS 内联。

    "configurations": {
        "production": {
          "optimization": {
            "styles": {
              "inlineCritical": false
            }
          }
        }
      }

为什么 Angular 这样做?

当浏览器呈现页面时,它必须等待 CSS 资源被下载和解析。它会给人一种(错误的)印象,即您的应用程序加载缓慢,并会影响 First Contentful Paint (FCP) 时间。

避免这种情况的常用技术是直接在 HTML 中内联 CSS,以避免额外的请求(这是 Lighthouse 推荐的)。但是你不想内联所有的 CSS,否则下载 HTML 的时间会增加。您只想内联关键 CSS 资源,即阻止呈现的资源,以及您的用户将看到的资源(您可以推迟 CSS 的其余部分)。

Angular CLI 在 v11.1 中引入了一个新选项来帮助我们解决这个问题:inlineCSS 然后,CLI 将在后台使用 critters 来提取应用程序的关键 CSS,并将它们直接内联到 HTML 中。 使用上述配置的 运行 ng build --prod 生成一个 index.html 文件,其中包含提取的关键 CSS 样式元素,并且通常的 styles.xxxxx.css 使用以下方式异步加载:

<link rel="stylesheet" href="styles.3d6bb69e3d075769b349.css" media="print" onload="this.media='all'">

有关 unsafe-inline CSP 关键字的更多信息:https://content-security-policy.com/unsafe-inline/