question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Integration of Module Federation with Material-UI overriding parent theme with defaults

See original GitHub issue

I 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 image

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.

image

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:closed
  • Created 2 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
ScriptedAlchemycommented, Apr 7, 2021

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 cache

1reaction
edwards-afterpaycommented, Apr 2, 2021

I 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 the ModuleFederationPlugin->shared the problem seems to go away.

shared: {
   react: {
    singleton: true,
    requiredVersion: deps.react,
  },
  "react-dom": {
    singleton: true,
    requiredVersion: deps["react-dom"],
  },
  "@material-ui/core": {
    singleton: true,
    requiredVersion: deps["@material-ui/core"]
  },
  "@material-ui/styles": {
    singleton: true,
    requiredVersion: deps["@material-ui/styles"]
  }
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Integration of Module Federation with Material-UI overriding parent ...
I ran into material-ui ThemeProvider issue. Every time I render a remote federated component which has Mui-Components I will see more default Mui...
Read more >
Nested theme providers not working correctly when used with ...
The issue is present in the latest release. I have searched the issues of this repository and believe that this is not a...
Read more >
Defining custom `ITheme` by overriding @material-ui's default ...
I've created a theme.d.ts file in my project and I've redefined the core module from @material-ui as the following:
Read more >
Revolutionizing Micro Frontends with Webpack 5, Module ...
In short, Module Federation allows JavaScript application to dynamically import code from another application at runtime. The module will build ...
Read more >
Best Material UI Alternatives Components - Sencha
Material UI is not always the best solution for every design use case. ... you to define styles to override the default material...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found