originjs / vite-plugin-federation

Module Federation for vite & rollup
Other
2.25k stars 234 forks source link

Dynamic Loading of MFE exposing multiple entries doesn't work #610

Closed yoniabitbolkryon closed 2 months ago

yoniabitbolkryon commented 2 months ago

Versions

Reproduction

MFE vite.config.ts:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import federation from "@originjs/vite-plugin-federation";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    federation({
      name: "pokemonList",
      filename: "remoteEntry.js",
      exposes: {
        "./PokemonList": "./src/components/PokemonList",
        "./PokemonList2": "./src/components/PokemonList2"
      },
      shared: ["react", "react-dom", "jotai"],
    }),
  ],
  build: {
    modulePreload: false,
    target: "esnext",
    minify: false,
    cssCodeSplit: false,
  },
});

Host vite.config.ts:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import federation from "@originjs/vite-plugin-federation";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    federation({
      name: "pokemonHome",
      remotes: {
        dummy: "dummy",
      },
      shared: ["react", "react-dom"],
    }),
  ],
  build: {
    modulePreload: false,
    target: "esnext",
    minify: false,
    cssCodeSplit: false,
  },
});

Host App.jsx:

import {lazy, useEffect, useState} from "react";
import {__federation_method_getRemote, __federation_method_setRemote} from "__federation__";
import "./App.css";

const loadComponent = (scope, module, remoteUrl) => {
    return async () => {
        console.log('loadComponent', scope, module, remoteUrl);
        try {
            __federation_method_setRemote(scope, {
                url: (typeof remoteUrl === 'string') ? () => Promise.resolve(remoteUrl) : remoteUrl,
                format: "esm",
                from: "vite",
            });

            return __federation_method_getRemote(scope, module);
        } catch (err) {
            console.error('loadComponent loading remote component', err);
        }
    };
};

const componentCache = new Map();
export const useFederatedComponent =(
    remoteUrl,
    scope,
    module
) => {
    const key = `${scope}-${module}`;
    const [Component, setComponent] = useState(null);

    useEffect(() => {
        if (Component) setComponent(null);
        // eslint-disable-next-line react-hooks/exhaustive-deps -- Only recalculate when key changes
    }, [key]);

    useEffect(() => {
        if (!Component) {
            const Comp = lazy(loadComponent(scope, module, remoteUrl));
            componentCache.set(key, Comp);
            setComponent(Comp);
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps -- key includes all dependencies (scope/module)
    }, [Component, key]);

    return {Component};
};

function App() {

    const {Component: PokemonList} =
        useFederatedComponent("http://localhost:5174/assets/remoteEntry.js", "pokemonList", "./PokemonList");
    const {Component: PokemonList2} =
        useFederatedComponent("http://localhost:5174/assets/remoteEntry.js", "pokemonList2", "./PokemonList2");

    return (
        <>
            <h3 style={{color: "#1e3a8a", fontSize: "20px"}}>
                Created using Vite + vite-plugin-federation
            </h3>
            {PokemonList ? <PokemonList/> : <></>}
            {PokemonList2 ? <PokemonList2/> : <></>}
        </>
    );
}

export default App;

Steps to reproduce

Project reproduction: vite.zip

What is Expected?

The Host should display 2 component showing list of Pokémon.

What is actually happening?

page is empty and Console has multiple errors:

Warning: lazy: Expected the result of a dynamic import() call. Instead received: () => {
  const [, addPokemons] = useAtom(addAllPokemons);
  const [pokemons$1] = useAtom(pokemons);
  const [, setSelectPokemon] = useSelectPokemon();
  const fetchPokemons = async () => {
    const response = await fetch(
      "https://raw.githubusercontent.com/kevinuehara/microfrontends/main/mocks/pokemonList.json"
    );
    const jsonData = await response.json();
    addPokemons(jsonData);
  };
  useEffect(() => {
    fetchPokemons();
  }, []);
  return /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: style.container, children: [
    /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("h1", { children: "Pokémon List Micro Frontend" }, void 0, false, {
      fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
      lineNumber: 29,
      columnNumber: 7
    }, globalThis),
    /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: style.pokemonCardContainer, children: pokemons$1.map((pokemon) => {
      return /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
        "div",
        {
          className: style.pokemonCard,
          onClick: () => setSelectPokemon(pokemon),
          children: [
            /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
              "img",
              {
                src: pokemon.sprite,
                "aria-label": `Image of pokemon ${pokemon.name}`
              },
              void 0,
              false,
              {
                fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
                lineNumber: 38,
                columnNumber: 15
              },
              globalThis
            ),
            /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("label", { children: pokemon.name }, void 0, false, {
              fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
              lineNumber: 42,
              columnNumber: 15
            }, globalThis)
          ]
        },
        pokemon.id,
        true,
        {
          fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
          lineNumber: 33,
          columnNumber: 13
        },
        globalThis
      );
    }) }, void 0, false, {
      fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
      lineNumber: 30,
      columnNumber: 7
    }, globalThis)
  ] }, void 0, true, {
    fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
    lineNumber: 28,
    columnNumber: 5
  }, globalThis);
}

Your code should look like: 
  const MyComponent = lazy(() => import('./MyComponent'))
    at App (http://localhost:5173/src/App.jsx?t=1720595273552:57:38)
printWarning @ chunk-3ON3CNAS.js?v=b0864ebc:137
error @ chunk-3ON3CNAS.js?v=b0864ebc:121
lazyInitializer @ chunk-3ON3CNAS.js?v=b0864ebc:899
resolveLazy @ chunk-FMOPAGIP.js?v=b0864ebc:9965
updateElement @ chunk-FMOPAGIP.js?v=b0864ebc:10058
updateSlot @ chunk-FMOPAGIP.js?v=b0864ebc:10147
reconcileChildrenArray @ chunk-FMOPAGIP.js?v=b0864ebc:10267
reconcileChildFibers2 @ chunk-FMOPAGIP.js?v=b0864ebc:10575
reconcileChildren @ chunk-FMOPAGIP.js?v=b0864ebc:14310
updateFunctionComponent @ chunk-FMOPAGIP.js?v=b0864ebc:14624
beginWork @ chunk-FMOPAGIP.js?v=b0864ebc:15942
beginWork$1 @ chunk-FMOPAGIP.js?v=b0864ebc:19779
performUnitOfWork @ chunk-FMOPAGIP.js?v=b0864ebc:19224
workLoopSync @ chunk-FMOPAGIP.js?v=b0864ebc:19163
renderRootSync @ chunk-FMOPAGIP.js?v=b0864ebc:19142
performConcurrentWorkOnRoot @ chunk-FMOPAGIP.js?v=b0864ebc:18704
workLoop @ chunk-FMOPAGIP.js?v=b0864ebc:195
flushWork @ chunk-FMOPAGIP.js?v=b0864ebc:174
performWorkUntilDeadline @ chunk-FMOPAGIP.js?v=b0864ebc:382
Show 19 more frames
Show lessUnderstand this error
App.jsx:7 loadComponent pokemonList2 ./PokemonList2 http://localhost:5174/assets/remoteEntry.js
chunk-3ON3CNAS.js?v=b0864ebc:137 Warning: lazy: Expected the result of a dynamic import() call. Instead received: () => {
  const [, addPokemons] = useAtom(addAllPokemons);
  const [pokemons$1] = useAtom(pokemons);
  const [, setSelectPokemon] = useSelectPokemon();
  const fetchPokemons = async () => {
    const response = await fetch(
      "https://raw.githubusercontent.com/kevinuehara/microfrontends/main/mocks/pokemonList.json"
    );
    const jsonData = await response.json();
    addPokemons(jsonData);
  };
  useEffect(() => {
    fetchPokemons();
  }, []);
  return /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: style.container, children: [
    /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("h1", { children: "Pokémon List Micro Frontend" }, void 0, false, {
      fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
      lineNumber: 29,
      columnNumber: 7
    }, globalThis),
    /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: style.pokemonCardContainer, children: pokemons$1.map((pokemon) => {
      return /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
        "div",
        {
          className: style.pokemonCard,
          onClick: () => setSelectPokemon(pokemon),
          children: [
            /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
              "img",
              {
                src: pokemon.sprite,
                "aria-label": `Image of pokemon ${pokemon.name}`
              },
              void 0,
              false,
              {
                fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
                lineNumber: 38,
                columnNumber: 15
              },
              globalThis
            ),
            /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("label", { children: pokemon.name }, void 0, false, {
              fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
              lineNumber: 42,
              columnNumber: 15
            }, globalThis)
          ]
        },
        pokemon.id,
        true,
        {
          fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
          lineNumber: 33,
          columnNumber: 13
        },
        globalThis
      );
    }) }, void 0, false, {
      fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
      lineNumber: 30,
      columnNumber: 7
    }, globalThis)
  ] }, void 0, true, {
    fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
    lineNumber: 28,
    columnNumber: 5
  }, globalThis);
}

Your code should look like: 
  const MyComponent = lazy(() => import('./MyComponent'))
    at App (http://localhost:5173/src/App.jsx?t=1720595273552:57:38)
printWarning @ chunk-3ON3CNAS.js?v=b0864ebc:137
error @ chunk-3ON3CNAS.js?v=b0864ebc:121
lazyInitializer @ chunk-3ON3CNAS.js?v=b0864ebc:899
resolveLazy @ chunk-FMOPAGIP.js?v=b0864ebc:9965
updateElement @ chunk-FMOPAGIP.js?v=b0864ebc:10058
updateSlot @ chunk-FMOPAGIP.js?v=b0864ebc:10147
reconcileChildrenArray @ chunk-FMOPAGIP.js?v=b0864ebc:10267
reconcileChildFibers2 @ chunk-FMOPAGIP.js?v=b0864ebc:10575
reconcileChildren @ chunk-FMOPAGIP.js?v=b0864ebc:14310
updateFunctionComponent @ chunk-FMOPAGIP.js?v=b0864ebc:14624
beginWork @ chunk-FMOPAGIP.js?v=b0864ebc:15942
beginWork$1 @ chunk-FMOPAGIP.js?v=b0864ebc:19779
performUnitOfWork @ chunk-FMOPAGIP.js?v=b0864ebc:19224
workLoopSync @ chunk-FMOPAGIP.js?v=b0864ebc:19163
renderRootSync @ chunk-FMOPAGIP.js?v=b0864ebc:19142
performConcurrentWorkOnRoot @ chunk-FMOPAGIP.js?v=b0864ebc:18704
workLoop @ chunk-FMOPAGIP.js?v=b0864ebc:195
flushWork @ chunk-FMOPAGIP.js?v=b0864ebc:174
performWorkUntilDeadline @ chunk-FMOPAGIP.js?v=b0864ebc:382
Show 19 more frames
Show lessUnderstand this error
chunk-3ON3CNAS.js?v=b0864ebc:137 Warning: lazy: Expected the result of a dynamic import() call. Instead received: () => {
  const [, addPokemons] = useAtom(addAllPokemons);
  const [pokemons$1] = useAtom(pokemons);
  const [, setSelectPokemon] = useSelectPokemon();
  const fetchPokemons = async () => {
    const response = await fetch(
      "https://raw.githubusercontent.com/kevinuehara/microfrontends/main/mocks/pokemonList.json"
    );
    const jsonData = await response.json();
    addPokemons(jsonData);
  };
  useEffect(() => {
    fetchPokemons();
  }, []);
  return /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: style.container, children: [
    /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("h1", { children: "Pokémon List Micro Frontend" }, void 0, false, {
      fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList2/index.tsx",
      lineNumber: 29,
      columnNumber: 7
    }, globalThis),
    /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: style.pokemonCardContainer, children: pokemons$1.map((pokemon) => {
      return /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
        "div",
        {
          className: style.pokemonCard,
          onClick: () => setSelectPokemon(pokemon),
          children: [
            /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
              "img",
              {
                src: pokemon.sprite,
                "aria-label": `Image of pokemon ${pokemon.name}`
              },
              void 0,
              false,
              {
                fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList2/index.tsx",
                lineNumber: 38,
                columnNumber: 15
              },
              globalThis
            ),
            /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("label", { children: pokemon.name }, void 0, false, {
              fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList2/index.tsx",
              lineNumber: 42,
              columnNumber: 15
            }, globalThis)
          ]
        },
        pokemon.id,
        true,
        {
          fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList2/index.tsx",
          lineNumber: 33,
          columnNumber: 13
        },
        globalThis
      );
    }) }, void 0, false, {
      fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList2/index.tsx",
      lineNumber: 30,
      columnNumber: 7
    }, globalThis)
  ] }, void 0, true, {
    fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList2/index.tsx",
    lineNumber: 28,
    columnNumber: 5
  }, globalThis);
}

Your code should look like: 
  const MyComponent = lazy(() => import('./MyComponent'))
    at App (http://localhost:5173/src/App.jsx?t=1720595273552:57:38)
printWarning @ chunk-3ON3CNAS.js?v=b0864ebc:137
error @ chunk-3ON3CNAS.js?v=b0864ebc:121
lazyInitializer @ chunk-3ON3CNAS.js?v=b0864ebc:899
resolveLazy @ chunk-FMOPAGIP.js?v=b0864ebc:9965
updateElement @ chunk-FMOPAGIP.js?v=b0864ebc:10058
updateSlot @ chunk-FMOPAGIP.js?v=b0864ebc:10147
reconcileChildrenArray @ chunk-FMOPAGIP.js?v=b0864ebc:10267
reconcileChildFibers2 @ chunk-FMOPAGIP.js?v=b0864ebc:10575
reconcileChildren @ chunk-FMOPAGIP.js?v=b0864ebc:14310
updateFunctionComponent @ chunk-FMOPAGIP.js?v=b0864ebc:14624
beginWork @ chunk-FMOPAGIP.js?v=b0864ebc:15942
beginWork$1 @ chunk-FMOPAGIP.js?v=b0864ebc:19779
performUnitOfWork @ chunk-FMOPAGIP.js?v=b0864ebc:19224
workLoopSync @ chunk-FMOPAGIP.js?v=b0864ebc:19163
renderRootSync @ chunk-FMOPAGIP.js?v=b0864ebc:19142
performConcurrentWorkOnRoot @ chunk-FMOPAGIP.js?v=b0864ebc:18704
workLoop @ chunk-FMOPAGIP.js?v=b0864ebc:195
flushWork @ chunk-FMOPAGIP.js?v=b0864ebc:174
performWorkUntilDeadline @ chunk-FMOPAGIP.js?v=b0864ebc:382
Show 19 more frames
Show lessUnderstand this error
chunk-3ON3CNAS.js?v=b0864ebc:137 Warning: lazy: Expected the result of a dynamic import() call. Instead received: () => {
  const [, addPokemons] = useAtom(addAllPokemons);
  const [pokemons$1] = useAtom(pokemons);
  const [, setSelectPokemon] = useSelectPokemon();
  const fetchPokemons = async () => {
    const response = await fetch(
      "https://raw.githubusercontent.com/kevinuehara/microfrontends/main/mocks/pokemonList.json"
    );
    const jsonData = await response.json();
    addPokemons(jsonData);
  };
  useEffect(() => {
    fetchPokemons();
  }, []);
  return /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: style.container, children: [
    /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("h1", { children: "Pokémon List Micro Frontend" }, void 0, false, {
      fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
      lineNumber: 29,
      columnNumber: 7
    }, globalThis),
    /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: style.pokemonCardContainer, children: pokemons$1.map((pokemon) => {
      return /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
        "div",
        {
          className: style.pokemonCard,
          onClick: () => setSelectPokemon(pokemon),
          children: [
            /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
              "img",
              {
                src: pokemon.sprite,
                "aria-label": `Image of pokemon ${pokemon.name}`
              },
              void 0,
              false,
              {
                fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
                lineNumber: 38,
                columnNumber: 15
              },
              globalThis
            ),
            /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("label", { children: pokemon.name }, void 0, false, {
              fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
              lineNumber: 42,
              columnNumber: 15
            }, globalThis)
          ]
        },
        pokemon.id,
        true,
        {
          fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
          lineNumber: 33,
          columnNumber: 13
        },
        globalThis
      );
    }) }, void 0, false, {
      fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
      lineNumber: 30,
      columnNumber: 7
    }, globalThis)
  ] }, void 0, true, {
    fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
    lineNumber: 28,
    columnNumber: 5
  }, globalThis);
}

Your code should look like: 
  const MyComponent = lazy(() => import('./MyComponent'))
    at Lazy
    at App (http://localhost:5173/src/App.jsx?t=1720595273552:57:38)
printWarning @ chunk-3ON3CNAS.js?v=b0864ebc:137
error @ chunk-3ON3CNAS.js?v=b0864ebc:121
lazyInitializer @ chunk-3ON3CNAS.js?v=b0864ebc:899
mountLazyComponent @ chunk-FMOPAGIP.js?v=b0864ebc:14840
beginWork @ chunk-FMOPAGIP.js?v=b0864ebc:15936
beginWork$1 @ chunk-FMOPAGIP.js?v=b0864ebc:19779
performUnitOfWork @ chunk-FMOPAGIP.js?v=b0864ebc:19224
workLoopSync @ chunk-FMOPAGIP.js?v=b0864ebc:19163
renderRootSync @ chunk-FMOPAGIP.js?v=b0864ebc:19142
performConcurrentWorkOnRoot @ chunk-FMOPAGIP.js?v=b0864ebc:18704
workLoop @ chunk-FMOPAGIP.js?v=b0864ebc:195
flushWork @ chunk-FMOPAGIP.js?v=b0864ebc:174
performWorkUntilDeadline @ chunk-FMOPAGIP.js?v=b0864ebc:382
Show 13 more frames
Show lessUnderstand this error
chunk-3ON3CNAS.js?v=b0864ebc:137 Warning: lazy: Expected the result of a dynamic import() call. Instead received: () => {
  const [, addPokemons] = useAtom(addAllPokemons);
  const [pokemons$1] = useAtom(pokemons);
  const [, setSelectPokemon] = useSelectPokemon();
  const fetchPokemons = async () => {
    const response = await fetch(
      "https://raw.githubusercontent.com/kevinuehara/microfrontends/main/mocks/pokemonList.json"
    );
    const jsonData = await response.json();
    addPokemons(jsonData);
  };
  useEffect(() => {
    fetchPokemons();
  }, []);
  return /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: style.container, children: [
    /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("h1", { children: "Pokémon List Micro Frontend" }, void 0, false, {
      fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
      lineNumber: 29,
      columnNumber: 7
    }, globalThis),
    /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("div", { className: style.pokemonCardContainer, children: pokemons$1.map((pokemon) => {
      return /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
        "div",
        {
          className: style.pokemonCard,
          onClick: () => setSelectPokemon(pokemon),
          children: [
            /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV(
              "img",
              {
                src: pokemon.sprite,
                "aria-label": `Image of pokemon ${pokemon.name}`
              },
              void 0,
              false,
              {
                fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
                lineNumber: 38,
                columnNumber: 15
              },
              globalThis
            ),
            /* @__PURE__ */ jsxDevRuntimeExports.jsxDEV("label", { children: pokemon.name }, void 0, false, {
              fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
              lineNumber: 42,
              columnNumber: 15
            }, globalThis)
          ]
        },
        pokemon.id,
        true,
        {
          fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
          lineNumber: 33,
          columnNumber: 13
        },
        globalThis
      );
    }) }, void 0, false, {
      fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
      lineNumber: 30,
      columnNumber: 7
    }, globalThis)
  ] }, void 0, true, {
    fileName: "C:/Users/AbitboY/Downloads/microfrontends-module-federation-main/vite/pokemons-list/src/components/PokemonList/index.tsx",
    lineNumber: 28,
    columnNumber: 5
  }, globalThis);
}

Your code should look like: 
  const MyComponent = lazy(() => import('./MyComponent'))
    at Lazy
    at App (http://localhost:5173/src/App.jsx?t=1720595273552:57:38)
printWarning @ chunk-3ON3CNAS.js?v=b0864ebc:137
error @ chunk-3ON3CNAS.js?v=b0864ebc:121
lazyInitializer @ chunk-3ON3CNAS.js?v=b0864ebc:899
mountLazyComponent @ chunk-FMOPAGIP.js?v=b0864ebc:14840
beginWork @ chunk-FMOPAGIP.js?v=b0864ebc:15936
callCallback2 @ chunk-FMOPAGIP.js?v=b0864ebc:3672
invokeGuardedCallbackDev @ chunk-FMOPAGIP.js?v=b0864ebc:3697
invokeGuardedCallback @ chunk-FMOPAGIP.js?v=b0864ebc:3731
beginWork$1 @ chunk-FMOPAGIP.js?v=b0864ebc:19791
performUnitOfWork @ chunk-FMOPAGIP.js?v=b0864ebc:19224
workLoopSync @ chunk-FMOPAGIP.js?v=b0864ebc:19163
renderRootSync @ chunk-FMOPAGIP.js?v=b0864ebc:19142
performConcurrentWorkOnRoot @ chunk-FMOPAGIP.js?v=b0864ebc:18704
workLoop @ chunk-FMOPAGIP.js?v=b0864ebc:195
flushWork @ chunk-FMOPAGIP.js?v=b0864ebc:174
performWorkUntilDeadline @ chunk-FMOPAGIP.js?v=b0864ebc:382
Show 16 more frames
Show lessUnderstand this error
chunk-FMOPAGIP.js?v=b0864ebc:14900 Uncaught Error: Element type is invalid. Received a promise that resolves to: undefined. Lazy element type must resolve to a class or function.
    at mountLazyComponent (chunk-FMOPAGIP.js?v=b0864ebc:14900:17)
    at beginWork (chunk-FMOPAGIP.js?v=b0864ebc:15936:22)
    at HTMLUnknownElement.callCallback2 (chunk-FMOPAGIP.js?v=b0864ebc:3672:22)
    at Object.invokeGuardedCallbackDev (chunk-FMOPAGIP.js?v=b0864ebc:3697:24)
    at invokeGuardedCallback (chunk-FMOPAGIP.js?v=b0864ebc:3731:39)
    at beginWork$1 (chunk-FMOPAGIP.js?v=b0864ebc:19791:15)
    at performUnitOfWork (chunk-FMOPAGIP.js?v=b0864ebc:19224:20)
    at workLoopSync (chunk-FMOPAGIP.js?v=b0864ebc:19163:13)
    at renderRootSync (chunk-FMOPAGIP.js?v=b0864ebc:19142:15)
    at performConcurrentWorkOnRoot (chunk-FMOPAGIP.js?v=b0864ebc:18704:83)
dawidmarczakcompany commented 2 months ago

Hey!

I had a similar issue. When you have multiple exposes in MFE the module federation plugin automatically changes the export in the federation entry point and then you don't have a default export.

In my case, the below fixes the issue, and modules were loaded correctly when there was a single or multiple exposes.

const remote = await federation.__federation_method_getRemote(moduleName, exposeName);
return "default" in remote ? remote : { default: remote };
yoniabitbolkryon commented 2 months ago

Hey!

I had a similar issue. When you have multiple exposes in MFE the module federation plugin automatically changes the export in the federation entry point and then you don't have a default export.

In my case, the below fixes the issue, and modules were loaded correctly when there was a single or multiple exposes.

const remote = await federation.__federation_method_getRemote(moduleName, exposeName);
return "default" in remote ? remote : { default: remote };

thank you, it worked! :)