Integration of Module Federation with Material-UI overriding parent theme with defaults
See original GitHub issueI ran into material-ui ThemeProvider issue. Every time I render a remote federated component which has Mui-Components I will see more default Mui <style>
getting injected into shell <head>
tag. I would have assumed the ThemeProvider from the parent shell will propagate all the way to the remote child apps. It didn’t but instead injects additional default theme to my parent app once I import the remote child app.
I am not really sure where should I post this problem - Mui or Module Federation. But feels like it’s a combination of both.
Before Module Fed - Setup:
shell
app bootstraps the ThemeProvider with custom theme. The Button rendered in the shell
shows correct custom theme.
import React from 'react';
import { theme } from './theme'
import { ThemeProvider } from "@material-ui/core/styles";
import { Button, CssBaseline } from "@material-ui/core";
const App = () => {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Button variant='contained' color='primary'>Parent button</Button>
</ThemeProvider>
)
}
export default App;
index.html
source
After - Problem as soon as I start adding Federated component:
import React from 'react';
import { theme } from './theme'
import { ThemeProvider } from "@material-ui/core/styles";
import { Button, CssBaseline } from "@material-ui/core";
import RemoteApp1 from "webRemoveApp1/App";
const RemoteApp2 = React.lazy(() => import("webRemoveApp2/App"));
const App = () => {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Button variant='contained' color='primary'>Parent button</Button>
<RemoteApp1 />
<RemoteApp2 />
</ThemeProvider>
)
}
export default App;
index.html
source, you will find 2 additional sets of <style>
being injected from each App (MuiTouchRipple, MuiButtonBase, MuiButton
), and because they have higher priority, it overwrites my parent Button’s theme back to defaults, same as the children.
theme.js
import { createMuiTheme } from '@material-ui/core/styles'
const themeConfig = {
palette: {
primary: {
main: '#008000', // green
}
}
}
export const theme = createMuiTheme(themeConfig)
RemoteApp1
import React from "react";
import { Button } from "@material-ui/core";
const App = () => {
return (
<div>App1
<Button variant='contained' color="primary">Child App1</Button>
</div>
)
}
export default App;
RemoteApp2
import React from "react";
import { Button } from "@material-ui/core";
const App = () => {
return (
<div>App2
<Button variant='contained' color="primary">Child App2</Button>
</div>
)
}
export default App;
Issue Analytics
- State:
- Created 2 years ago
- Comments:5 (2 by maintainers)
Top GitHub Comments
yes, anything that passed context needs to be a singleton, theming and styling usually have caches or context busses that needs to be centralized and shared. If context-related stuff isn’t working, its most likely a missing
shared
key, take a look in the node module folder and see what else it depends on that might be a nested dep of something you’re sharing. like a cacheI may have figured it out, it seems under the hood
@material-ui/styles
used has to be singleton. Just like React has to be singleton to ensure React Context behaves correctly. Once I added both the@material-ui/core
and@material-ui/styles
in theModuleFederationPlugin->shared
the problem seems to go away.