1

I'm trying to use import maps with React and Vite. I have a React Vite application called app1 with the following vite.config.ts:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { resolve } from "node:path";

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
  build: {
    target: "esnext",
    manifest: true,
    rollupOptions: {
      input: {
        [process.env.npm_package_name!]: resolve(__dirname, "src/main.tsx"),
      },
      external: ["react", "react-dom"],
      output: {
        globals: {
          react: "React",
          "react-dom": "React-dom",
          "react/jsx-runtime": "react/jsx-runtime",
        },
      },
    },
  },
});

This configuration generates the JavaScript and CSS files, as well as the manifest. After building, I upload the files to a local CDN server. When I navigate to http://localhost:8080/app1-D0fBYSKJ.js, I can correctly see the built code.

I also have a shell application that loads this app. To import the import map, I use the following code in the index.html file:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React + TS</title>
    <script type="module">
      async function loadAndApplyImportMap() {
        const response = await fetch(`${import.meta.env.VITE_SERVER_URL}/get-import-map`);
        if (!response.ok) {
          throw new Error(`Response status: ${response.status}`);
        }
        const importMap = await response.json();
        const script = document.createElement("script");
        script.type = "importmap";
        script.textContent = JSON.stringify(importMap);
        document.head.prepend(script);
      }

      try {
        await loadAndApplyImportMap();
        import("./src/main.tsx");
      } catch (error) {
        console.error(error.message);
      }
    </script>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

When I call get-import-map, I receive the apps in this format:

{
    "imports": {
        "app1": "http://localhost:8080/app1-D0fBYSKJ.js",
        "app2": "http://localhost:8080/app2-nsuvAHz_.js"
    }
}

I then attempt to load the application using the following code:

const RemoteComponentLoader = ({ packageName }: { packageName: string }) => {
  const Component = lazy(() => import(packageName));

  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Component />
    </Suspense>
  );
};

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
      <RemoteComponentLoader packageName="app1" />
  </React.StrictMode>
);

However, I am encountering the following error:

Uncaught TypeError: Failed to resolve module specifier 'app1'

What else am I missing? What are the steps to make import maps work with React and Vite? I couldn't find an example of this approach, where I can build and import my applications using import maps.

I found this article: You Might Not Need Module Federation: Orchestrate your Microfrontends at Runtime with Import Maps | Mercedes-Benz.io, which is exactly what I want but it uses Vue and it didn't seem to work using React and Vite.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.