Module federation display a blank page for a few seconds when a remote is unavailable

Viewed 264

I have a micro frontend React application using Webpack module federation. My setup is an host application and a remote1 application.

Since I configured "react" as a shared dependency between the 2 apps, I found out that if remote1 is unavailable, the host application will display a blank page until the request for remote1/remoteEntry.js script fail after after a few seconds.

I wasn't expecting this behavior. I was expecting the host application to render my React application immediatly while Module Federation is trying to load all the remotes and show some kind of managed Spinner from my app.

It seems like the host application will not render until all the remotes script requests have resolved.

Is there any way to circumvent this behavior?

I made it work with Dynamic Remote Containers but I would rather leverage ModuleFederationPlugin remotes config section.

Here's my config for the host app:

new ModuleFederationPlugin({
  name: "host",
  remotes: {
    remote1: "remote1@http://localhost:8081/remoteEntry.js"
  },
  shared: {
    "react": {
      singleton: true,
      eager: true,
      requiredVersion: deps["react"]
    },
    "react-dom": {
      singleton: true,
      eager: true,
      requiredVersion: deps["react-dom"]
    },
  }
})

Here's my config for the remote1 app:

new ModuleFederationPlugin({
  name: "remote1",
  filename: "remoteEntry.js",
  exposes: {
    "./register": "./src/register"
  },
  shared: {
    "react": {
      singleton: true,
      requiredVersion: deps["react"]
    },
    "react-dom": {
      singleton: true,
      requiredVersion: deps["react-dom"]
    }
  }
})

Also, all my React bootstrapping code is in a bootstrap.jsx file included with a dynamic import from the index.js file.

1 Answers

A simple solution integrated with React is to use Suspense
From the React docs :
React.Suspense lets you specify the loading indicator in case some components in the tree below it are not yet ready to render.
Here is an example for how to host:

//App.jsx
import React, {Suspense} from 'react';
const App1 = React.lazy(() => import("app1/App"));
function App() {
    return (
        <div>
            <h2>I am the Container App!</h2>
            <Suspense fallback={"loading..."}>
                <App1/>
            </Suspense>
        </div>
    );
}

export default App;

Take aways:

  • Suspense is built to support asynchronic operations (loading code, data, images, etc) though today, lazy loading components is the only use case supported.
  • It also allows you to specify what to do (like a catch block!) until it's done - ie <Suspense fallback={<Spinner />}>

Related read

Related