5

I recently made a federated module host that is federating the Header and the Footer of a site. Everything works as expected, but I am trying to build in some fallbacks if the request to the federated host fails.

new ModuleFederationPlugin({
      name: 'app',
      remotes: {
        app2: 'app2@https:/example.com/remoteEntry.js',
        
      },
      shared: { react: { singleton: true, eager: true }, 'react-dom': { singleton: true, eager: true } },
    }),

If I block the request to https:/example.com/remoteEntry.js I get a the webpack error below. Ideally I would like to load a basic fallback header or just no header than the page completely dying

(error: https://example.com/remoteEntry.js1)
while loading "./Footer" from webpack/container/reference/app2

2 Answers2

5

I know it's a bit late, but I developed this solution, and possibly it can help someone else with Webpack@5 and Module Federation. It's also based on Dynamic Remotes.

https://webpack.js.org/concepts/module-federation/#promise-based-dynamic-remotes

new ModuleFederationPlugin({
      name: "app",
      remotes: {
        app2: `promise new Promise(resolve => {
          // This part depends on how you plan on hosting and versioning your federated modules
          const remoteUrlWithVersion = 'https:/example.com/remoteEntry.js'
          const script = document.createElement('script')
          script.src = remoteUrlWithVersion

          script.onload = () => {
            // the injected script has loaded and is available on window
            // we can now resolve this Promise
            const proxy = {
              get: (request) => {
                // Note the name of the module
                return window.app2.get(request);
              },
              init: (arg) => {
                try {
                  // Note the name of the module
                  return window.app2.init(arg)
                } catch(e) {
                  console.log('remote container already initialized')
                }
              }
            }
            resolve(proxy)
          }
          script.onerror = (error) => {
            console.error('error loading remote container')
            const proxy = {
              get: (request) => {
                // If the service is down it will render this content
                return Promise.resolve(() => () => "I'm dead");
              },
              init: (arg) => {
                return;
              }
            }
            resolve(proxy)
          }
          // inject this script with the src set to the versioned remoteEntry.js
          document.head.appendChild(script);
        })
        `
      },
      exposes: {},
      shared: {
        ...deps,
        react: {
          singleton: true,
          eager: true,
          requiredVersion: deps.react,
        },
        "react-dom": {
          singleton: true,
          eager: true,
          requiredVersion: deps["react-dom"],
        },
      },
    }),
1

I found a decision.

Checkout this article https://habr.com/ru/post/554682/ - the article is in Russian, but you can use a translator.

Pay attention to the hook - useDynamicScript and handlers onload and onerror

The point is to independently check whether it is available remoteEntry.js from remote host. If remoteEntry.js is not available, do not download the remote component, otherwise try to download. The probability that the component will load in this case is very high.

But if when loading remoteEntry.js an error will occur, we will process it, and the error will not be thrown to the console.

Hydrock
  • 133
  • 8