如何防止MaterialUI React组件向<style>标签中注入<head>标签

问题描述 投票:0回答:1

我最近将 MaterialUI 添加到我的 React 项目中,我看到标签中出现了一堆标签,这导致我的内容安全策略出现问题。

css reactjs material-ui styled-components emotion
1个回答
0
投票

为了防止 Material-UI (MUI) 组件将标签直接注入到标签中,您可以将 Material-UI 配置为使用 CSS-in-JS 样式 解决方案,例如 JSS。以下是您在项目中调整它的方法,以保持对样式注入位置的控制,并避免与您的内容安全策略 (CSP) 发生冲突。

解决方案 1: 使用 Styled Engine Provider 进行服务器端渲染 (SSR) 切换到 Emotion 或 Styled Components:Material-UI 从版本 5 开始使用 Emotion 作为默认样式引擎,但它也支持 Styled Components。通过允许预编译 CSS 提取,这两个库都可以在不动态注入样式的情况下工作,这有助于绕过 CSP 问题。

带有情感的服务器端渲染(SSR):使用SSR时,Material-UI可以将样式直接注入HTML中,而不是动态地将它们附加到标签中。请按照以下步骤操作:

安装所需的依赖项(如果尚未安装):

npm install @emotion/react @emotion/server @emotion/styled

在主服务器文件(例如 server.js 或 index.js)中配置 SSR,以确保在服务器渲染期间渲染 CSS 并将其添加到初始 HTML。

import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { ServerStyleSheets } from '@mui/styles';  // use @emotion/react if MUI5
import App from './App';

const sheets = new ServerStyleSheets();
const html = ReactDOMServer.renderToString(sheets.collect(<App />));
const css = sheets.toString();  // This extracts the styles as a string.

const fullHtml = `
  <!DOCTYPE html>
  <html lang="en">
  <head>
    <style>${css}</style>
  </head>
  <body>
    <div id="root">${html}</div>
  </body>
  </html>
`;

这种方法确保样式在 HTML 文档本身中静态呈现,因此无需动态注入样式。

解决方案 2: 使用 StyledEngineProvider 来确定样式范围 您还可以通过使用 StyledEngineProvider 包装您的应用程序来控制注入 Material-UI 样式的位置:

从 Material-UI 核心导入 StyledEngineProvider 并将其包装在您的应用程序中:

import { StyledEngineProvider } from '@mui/material/styles';
import App from './App';

function Main() {
  return (
    <StyledEngineProvider injectFirst>
      <App />
    </StyledEngineProvider>
  );
}
  • injectFirst
    设置为 true 可确保将 MUI 样式插入到应用程序中的其他样式之前,这可能有助于解决特定的 CSP 策略和排序问题。

解决方案3:内联关键CSS

如果您有一小组关键样式,请考虑手动提取这些样式并将它们内联到 HTML 中。 Material-UI 提供了 ServerStyleSheets 中的 toString() 等工具来提取生成的 CSS,您可以将此 CSS 作为块的一部分直接放置在 HTML 中。

其他注意事项:

  • 设置带有 Nonce 的 CSP 标头:如果您仍然需要动态注入样式,请考虑向 CSP 标头和注入的样式添加一个 Nonce 以符合 CSP。
  • 在生产版本中提取 CSS:一些捆绑器(例如 Webpack)具有可以提取 CSS 的插件。例如,使用 mini-css-extract-plugin 可以让您将 CSS 提取到一个单独的文件中,然后可以在不动态注入标签的情况下链接该文件。

通过实施这些解决方案之一,您应该能够控制 Material-UI 样式的处理方式并避免内容安全策略出现问题。

© www.soinside.com 2019 - 2024. All rights reserved.