module-federation-examples icon indicating copy to clipboard operation
module-federation-examples copied to clipboard

Loading remote React SPA module (mui theme object) into static props

Open kueben96 opened this issue 2 years ago • 3 comments

Hey,

I have been struggling importing my remote MUI theme into my next js application for a while now. I managed to import it on the client side but this leads the HTML source code to only provide my loading indicator div. what i want is to load the theme as static prop and pass it into the whole application.

As far as i understood, i cant import the module in static props as it is a client side operation.

is there another way?

Thanks!


import { ThemeProvider } from '@mui/material';
import React, { useEffect } from 'react';

function MyApp({ Component, pageProps, remoteTheme }) {
  const themeRef = React.useRef(false);
  const [theme, setTheme] = React.useState(null);
  console.log("remoteTheme")
  console.log(remoteTheme)

  useEffect(() => {
    const loadTheme = async () => {
      if (themeRef.current === false) {
        try {
          const sharedTheme = await import('theme/theme');
          setTheme(sharedTheme.default);
        } catch (error) {
          console.error('Error loading shared theme', error);
        }
      }
      themeRef.current = true;
    };

    loadTheme();
  }, []);

  if (!theme) {
    // Return a loading indicator or any other UI element while waiting for the theme to load
    return (
      <div>
        Loading theme...
      </div>
    );
  }

  return (
    <ThemeProvider theme={theme}>
      <Component {...pageProps} />
    </ThemeProvider>
  );
}


// !! this gives the following error 

export default MyApp;
export async function getStaticProps() {
  const { default: remoteTheme } = await import('theme/theme');
  return {
    props: {
      remoteTheme
    }
  };
}


TypeError: __webpack_modules__[moduleId] is not a function

This error happened while generating the page. Any console logs will be displayed in the terminal window.

my package json

{
  "name": "landing-page",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev -p 8084",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@emotion/react": "^11.11.1",
    "@emotion/styled": "^11.11.0",
    "@module-federation/nextjs-mf": "5.2.1",
    "@mui/icons-material": "^5.14.3",
    "@mui/material": "^5.14.5",
    "next": "12.3.4",
    "react": "18.2.0",
    "react-dom": "18.2.0"
  },
  "devDependencies": {
    "eslint": "8.14.0",
    "eslint-config-next": "12.1.5"
  }
}


next config:


const NextFederationPlugin = require('@module-federation/nextjs-mf');

module.exports = {
  webpack(config, options) {
    const { isServer } = options;
    config.plugins.push(
      new NextFederationPlugin({
        name: 'landing',
        filename: 'static/chunks/remoteEntry.js',
        exposes: {
          './NextApp': './pages/index.js',
          "./BB8": "./components/BB8",
          "./Button": "./components/Button",
          "./ServicesCard": "./components/ServicesCard",
        },
        remotes: {
          theme: 'theme@http://localhost:8085/remoteEntry.js',
        },
        shared: {
          '@mui/material': {
            singleton: true, // Ensure only one instance is loaded
          },
          react: {
            requiredVersion: false,
            singleton: true,
          },
        },
        extraOptions: {
          skipSharingNextInternals: true,
        },

      })
    );

    return config;
  },
  reactStrictMode: true,
};


kueben96 avatar Sep 06 '23 12:09 kueben96

Is remote online at compile time?

ScriptedAlchemy avatar Sep 07 '23 01:09 ScriptedAlchemy

yes it is

kueben96 avatar Sep 07 '23 09:09 kueben96

Try sharing @mui/ with slash on end. To force anything starting with mui to share. It's usually internal module that needs to be singleton too as mui is large monorepo

ScriptedAlchemy avatar Sep 13 '23 09:09 ScriptedAlchemy