2

I would like to import a simple mui component.

My component:

import Button from "@mui/material/Button";

export default function Bar() {
  return <Button variant="contained">Contained</Button>;
};

I use vite (with rolldown-vite) to build this component:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  define: {
    "process.env.NODE_ENV": JSON.stringify("production")
  },
  build: {
    lib: {
      entry: "src/Index.tsx",
      name: "mycomponent",
      formats: ["es"]
    },
  },
  external: [
    "react",
     "@mui/material",
     "@emotion/react",
     "@emotion/styled"
   ],
   output: {
     globals: {
       react: "React",
       "@mui/material": "MaterialUI",
       "@emotion/react": "EmotionReact",
        "@emotion/styled": "EmotionStyled",
     },
   },
})

I use an http server to serve bundled js file. I can reach it with curl

When importing it with:

  export const Plugins = ({ url}: { url: string }) => {
  const [Comp, setComponent] = useState<FC>();

      import(url)
      .then((component) => setComponent(() => component.default))
      .catch((err: unknown) => {
         console.log(err);
      });

      return (
        <Comp />
      );

I get

(new TypeError("Wrong module specifier", ""))
%s

%s

I don't install react and mui deps into component because I installed them into my main app

I don't know why I get this issue.

I do something wrong during build / import ?

Update: I try to import it without lazy, get same issue

Update2: I added react and all @mui dependencies into my lib dependencies. I loaded my component:

import Bar from "http://localhost:8012/plugins/test/Foo.js"
return (
      <Bar />
  );

Now I get

(new TypeError("can't access property \"useContext\", w.H is null", "http://localhost:8012/plugins/test/foo.js", 266))
%s

%s
 An error occurred in the <ForwardRef> component. Consider adding an error boundary to your tree to customize error handling behavior.
[2025-10-27T11:44:31Z ERROR script::dom::console] (new TypeError("can't access property \"useContext\", w.H is null", "http://localhost:8012/plugins/test/foo.js", 266))

Update3: I tried without Lazy / Suspense, still get (new TypeError("Wrong module specifier", ""))

Update4: I installed my component into package.json, import default function and rendered the function. It works as expected. But this is exactly what I tried to avoid. My goal is to load my component from fs or served through an http server (Like I do currently)

Update5: I simplify my component:

function Bar() {
  return (
    <h1>hello from Bar</h1>
  );
}
export default Bar;

I can successfully import it. So I guess issue is from mui

5
  • Is it possible for you to create a codesandbox to reproduce the issue? Or a github link? Commented Oct 24 at 4:12
  • This error is related module imports. Somewhere in your code, you are not properly importing component or module. It says you are not specifying a module correctly. Check your exports too. Commented Oct 24 at 7:26
  • Also, I don't think you can pass an URL to the import function in lazy function. It should be a relative/local path like ./Mycomponent.js Commented Oct 24 at 7:32
  • Are you trying to implement microfrontend in your application? If yes, then you need to use module federation provided by vite to connect to remote apps Commented Oct 24 at 10:35
  • I don't know what is module federation. I would like to create a mui component, bundle it with vite (without react and mui deps) and load it into another react app with react and mui already installed Commented Oct 24 at 11:10

2 Answers 2

0

I'm closing it.

I can import a component with react but not mui dependencies. Issues is from Mui

Sign up to request clarification or add additional context in comments.

Comments

-1

The way you are importing the module is incorrect. You need to dynamically import it. Something like below:

useEffect(() => {
    import("http://localhost:8012/plugins/test/foo.js")
      .then((component) => setFoo(() => component.default))
      .catch((err) => console.error("Failed to load Foo:", err));
  }, []);

Also, because you need to specify that the imported module must use the libraries of the host application. So add rollup options in your vite config.

rollupOptions: {
      // These will NOT be bundled — expected from host
      external: [
        "react",
        "react-dom",
        "@mui/material",
        "@mui/icons-material",
        "@emotion/react",
        "@emotion/styled"
      ],
      output: {
        globals: {
          react: "React",
          "react-dom": "ReactDOM",
          "@mui/material": "MaterialUI",
          "@mui/icons-material": "MaterialIcons",
          "@emotion/react": "EmotionReact",
          "@emotion/styled": "EmotionStyled",
        },
      },
    },

Give this a try and let me know if it works.

8 Comments

with that, I still get (new TypeError("Wrong module specifier", ""))
Can you please provide a link to codesandbox reproducing your issue? or maybe a github link with your code?
Why would you put the import(…) in an effect? OP wants to use React.lazy.
It was just to check if the import is working fine or not.
Still no reason to use an effect, just calling the test function from the top level would have sufficed for that.
I need to use useEffect because the url is dynamic, I call a fn which return url before importing it
@Vana How so? In your question the url is defined as a const, please update the question if you think you need a function. Btw I'm pretty certain that you cannot (or at least should not) use lazy inside of a component, i.e. where the url depends on the props or state or something.
I updated my post to reflet the tries I do. I drop lazy and useEffect.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.