我们正在尝试将 Single spa 与 React 和 Material UI 集成。 我们有 2 个带有 Material UI 的 React 应用程序:
当我们集成这两个组件时,我们会出现以下错误:
看起来此应用程序中初始化了多个
@material-ui/styles
实例。这可能会导致主题传播问题、类名损坏、特异性问题,并在没有充分理由的情况下使您的应用程序变得更大。请参阅 https://material-ui.com/r/styles-instance-warning 了解更多信息。
配置文件是这样的:
webpack.config。 通过此配置,我们希望外部化,以便它使用根容器应用程序中存在的材质 ui 依赖项。
index.js。我们正在注册微前端。
index.html 我们正在使用systemjs来加载材质模块和微前端。
我们按照本页建议的步骤操作,但没有得到任何满意的结果:
https://material-ui.com/getting-started/faq/#i-have-several-instances-of-styles-on-the-page
我也一直在单一 Spa 微前端中的材质 UI 上苦苦挣扎,因为我对材质 UI 也有多个依赖项,这导致了随机渲染错误。
为了防止这种情况,您需要使用material-ui作为浏览器内模块,这样您的微前端就只有一份副本可以使用。为此,它需要与 SystemJS 兼容。更多信息:https://single-spa.js.org/docs/recommended-setup/#systemjs
为此,最简单的方法是使用 UMD 脚本。例如,如果您使用@material-ui/core版本4.11.3,您将需要这个脚本:
“https://cdn.jsdelivr.net/npm/@material-ui/[email protected]/umd/material-ui.production.min.js”
您必须使用其余的导入映射来加载该脚本:
例如:
<script type="systemjs-importmap">
{
"imports": {
"react": "https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js",
"react-dom": "https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js",
"single-spa": "https://cdn.jsdelivr.net/npm/[email protected]/lib/system/single-spa.min.js",
"rxjs": "https://cdn.jsdelivr.net/npm/@esm-bundle/[email protected]/system/es2015/rxjs.min.js",
"@material-ui/core": "https://cdn.jsdelivr.net/npm/@material-ui/[email protected]/umd/material-ui.production.min.js"
}
}
</script>
另一种可能性是使用 JSPM 将依赖项加载为导入映射。您可以在此处找到示例:https://github.com/jspm/project/issues/99
最后,您始终可以将依赖项打包到共享组件之一中并从那里共享它。由于您的共享组件是浏览器内模块,因此您将只有一份副本。
希望有用
我的设置与上述评论相同,但它并没有完全解决我的多个微前端的问题。为我解决这个问题的是:
我相信每个微前端都将自己的样式表注入到 DOM 中,无论是否通过调用 makeStyles,我并不完全确定。您可以在此示例中看到这一点 - https://d4e2yqa5hvu3s.cloudfront.net/ 通过检查源代码并查看 head 标签 - 有两个 MuiTypography。其源代码在本文中链接。我所做的是确保材质 ui 组件/样式的导入全部一致。因此,如果您在导入映射中声明:
{
"@material-ui/core": "<location of js>"
}
那么您的组件的所有导入都必须遵循:
import { x } from '@material-ui/core';
我还为每个样式类添加了每个微前端的唯一名称和种子(请参阅上面的文章和此处)。喜欢:
import { ThemeProvider, StylesProvider, createGenerateClassName } from '@material-ui/core';
const generateClassName = createGenerateClassName({
disableGlobal: true,
productionPrefix: 'foo', // defaults to 'jss'
seed: 'bar', // defaults to ''
});
...
<StylesProvider generateClassName={generateClassName}>
<ThemeProvider theme={myTheme}>
...
我相信我已经缓解了任何问题(样式/传播损坏),并且页面上有关多种样式的警告现已消失,但如果有人有更多想法,我很想听听它们:)
还需要将material-ui放置在webpack外部中。