I currently have multiple React v17 apps which utilise Module Federation from Webpack 5. I would like for my MUI 5 theme to be shared across all of these micro frontends without having a there own ThemeProvider
wrapped around each exposed component. At present, APP 1 (Shell) adds a custom theme into the MUI ThemeProvider
and all Micro UI's are lazy loaded as children. The custom theme works for the container components but not for the micro frontend components. I am following a micro frontend architecture with the following configuration:
...and so forth for all other micro frontends.
APP 1 - Module federation config:
const { ModuleFederationPlugin } = require('webpack').container
const { shared } = require('./shared/shared')
const homePage = 'https://localhost:8084';
var moduleFedConfig = new ModuleFederationPlugin({
name: 'container',
filename: 'remoteEntry.js',
remotes: {
homePage: `homePage@${homePage}/remoteEntry.js`,
},
shared: shared,
});
APP 2 - Module federation config:
const { ModuleFederationPlugin } = require('webpack').container;
const { shared } = require('./shared/shared');
var moduleFedConfig = new ModuleFederationPlugin({
name: 'homePage',
filename: 'remoteEntry.js',
exposes: {
'./HomePage': './src/page/HomePage',
},
shared: shared,
});
module.exports = { moduleFedConfig };
Module federation shared dependencies config for both APP1 & APP2
const deps = require('../../../package.json').dependencies;
var shared = {
react: {
singleton: true,
requiredVersion: '*',
},
'react-dom': {
singleton: true,
requiredVersion: '*',
},
'react-router-dom': {
singleton: true,
requiredVersion: '*',
},
'@okta/okta-auth-js/': {
singleton: true,
requiredVersion: 'auto',
},
'@okta/okta-react': {
singleton: true,
requiredVersion: 'auto',
},
'@reduxjs/toolkit': {
singleton: true,
requiredVersion: deps['@reduxjs/toolkit'],
},
'react-redux': {
singleton: true,
requiredVersion: deps['react-redux'],
},
'@emotion/react/' : {
singleton: true,
requiredVersion: '*',
},
'@emotion/styled' : {
singleton: true,
requiredVersion: '*',
},
'@mui/material' : {
singleton: true,
requiredVersion: '*',
},
};
module.exports = { shared };
APP 1 (Shell) - Snip of theme provider code:
React.useEffect(() => {
const newIsLoaded =
themeData.elementStyles !== null && themeData.theme !== null
setIsThemeLoaded(newIsLoaded)
}, [themeData.elementStyles, themeData.theme])
return !isLoginRedirect &&
authState?.isAuthenticated &&
isThemeLoaded &&
themeData.theme ? (
<ThemeProvider theme={themeData.theme}>
<CssBaseline />
<AppContainer /> //All micro front end components are rendered within here
</ThemeProvider>
) : (
<Loading fadeIn />
)
I would expect that because all the MUI modules are being shared as a singleton, all theme data setup in the initial shell would be accessible in the child micro frontend components.
Just to confirm as well that RTK & RTK Query work perfectly when shared so I suspect I'm missing something when adding a module to be shared for MUI 5 maybe?
If you need anything further then please don't hesitate to ask.
Thank you in advance.
I was able to resolve the issue by using an MF library called importRemote that lazy loads the components rather than the exposed components being loaded when the shell/container has started.