reactjsvitelazy-loadingdynamic-import

Why does adding lazy loading to a React Vite project result in an empty root node?


I am developing an app using React (Typescript) and Vite. To reduce bundle size, I want to implement code splitting, using React's lazy function. I am keen not to introduce a 3rd party library for this.

But when I run the app, all I see is a blank page, and devtools reveals that the App component has not been added under the root node:

<body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
</body>

What am I missing here?


So we initialise a new project using npm create vite@latest and remove some of the boilerplate.

We create a really basic component MyComponent:

// MyComponent.tsx
const MyComponent = () => {
  return <p>component text</p>;
};

export default MyComponent;

and lazily import it into App.tsx

// App.tsx
import { lazy } from "react";
import "./App.css";

function App() {
  const MyComponent = lazy(() => import("./MyComponent"));
  return (
    <>
      <h1>My page</h1>
      <MyComponent />
    </>
  );
}

export default App;

But when we run the app, all we see is a blank page, and devtools reveals that the App component has not been added under the root node.

a blank webpage in chrome with the devtools inspector open.

Link to a repo containing a minimal example

I am at a loss of what else to try.


Solution

  • The React docs specifies that you have to declare the lazy import components outside of the scope of a component.

    You have to import them just like you would for regular imports: at the top of your tsx file

    // App.tsx
    import { lazy } from "react";
    import "./App.css";
    
    const MyComponent = lazy(() => import("./MyComponent"));
    
    function App() {
      return (
        <>
          <h1>My page</h1>
          <MyComponent />
        </>
      );
    }
    
    export default App;