0

我们正在尝试将 Single spa 与 React 和 Material UI 集成。我们有 2 个带有 Material UI 的 React 应用程序:

  1. 根容器。
  2. 微前端(水疗应用程序)。

当我们集成这两个组件时,我们会遇到以下错误:

看起来@material-ui/styles此应用程序中有几个已初始化的实例。这可能会导致主题传播问题、损坏的类名、特殊性问题,并在没有充分理由的情况下使您的应用程序变大。有关详细信息,请参阅https://material-ui.com/r/styles-instance-warning

配置文件是这样的:

webpack.config。 使用此配置,我们希望将其外部化,以便它使用根容器应用程序中存在的材料 ui 依赖项。

webpack.config.js

索引.js。我们正在注册微前端。

index.js

index.html我们正在使用 systemjs 来加载材质模块和微前端。

在此处输入图像描述

我们按照本页建议的步骤操作,但没有得到任何满意的结果:

https://material-ui.com/getting-started/faq/#i-have-several-instances-of-styles-on-the-page

4

2 回答 2

1

我的设置与上述评论相同,但它并没有完全解决多个微前端的问题。为我解决的问题是:

我相信每个微前端都将自己的样式表注入到 DOM 中,无论是否通过调用 makeStyles,我都不完全确定。您可以在此示例中看到这一点 - https://d4e2yqa5hvu3s.cloudfront.net/通过检查源代码并查看头部标签 - 有两个 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}>
  ...

我相信我已经缓解了任何问题(损坏的样式/传播),并且关于页面上多个样式的警告现在已经消失,但是如果有人有更多的想法,我很想听听他们:)

于 2021-04-16T16:21:01.563 回答
1

我也一直在为 Single Spa 微前端中的材质 UI 苦苦挣扎,因为我对 material-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/core@4.11.3/umd/material-ui.production.min.js”

您必须将该脚本与其余的导入映射一起加载:

例如:

    <script type="systemjs-importmap">
      {
        "imports": {
          "react": "https://cdn.jsdelivr.net/npm/react@17.0.1/umd/react.production.min.js",
          "react-dom": "https://cdn.jsdelivr.net/npm/react-dom@17.0.1/umd/react-dom.production.min.js",
          "single-spa": "https://cdn.jsdelivr.net/npm/single-spa@5.8.2/lib/system/single-spa.min.js",
          "rxjs": "https://cdn.jsdelivr.net/npm/@esm-bundle/rxjs@6.6.6/system/es2015/rxjs.min.js",
          "@material-ui/core": "https://cdn.jsdelivr.net/npm/@material-ui/core@4.11.3/umd/material-ui.production.min.js"
        }
      }
    </script>

另一种可能性是使用 JSPM 将您的依赖项加载为导入映射。你可以在这里找到一个例子:https ://github.com/jspm/project/issues/99

最后,您始终可以将您的依赖项打包到您的一个共享组件中并从那里共享它。由于您的共享组件是浏览器内的模块,因此您将只有一份副本。

我希望这很有用

于 2021-03-30T13:03:33.437 回答