我最近将 MaterialUI 添加到我的 React 项目中,我看到标签中出现了一堆标签,这导致我的内容安全策略出现问题。
为了防止 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 中。
其他注意事项:
通过实施这些解决方案之一,您应该能够控制 Material-UI 样式的处理方式并避免内容安全策略出现问题。