webpack: Remote can crash host app when using ModuleFederationPlugin

Bug report

What is the current behavior?

An incorrectly configured remote can crash its host app

If the current behavior is a bug, please provide the steps to reproduce.

https://github.com/module-federation/module-federation-examples/blob/master/basic-host-remote On this line change the value of publicPath to "/"

app2 still runs fine by itself app1 throws a ChunkLoadError Not only can the error not be caught in App.js, App.js and bootstrap.js don’t even run

What is the expected behavior?

Remotes should never be able to crash their host apps. The dynamic import should return a promise that can be caught if needed, not throw strange errors that take down the whole app. If a team can deploy a broken remote that takes down every live app that consumes it, it means the whole federated network is unacceptably fragile.

Other relevant information: webpack version: 5.4.0 Node.js version: 12 Operating System: Mac

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 15
  • Comments: 20 (7 by maintainers)

Most upvoted comments

And what do you want? public path is wrong so you get the error

@ramesh-murugan-at-philips

As @ScriptedAlchemy said, you can use the advanced api for dynamic remotes to have more control over script loading.

I adapted / simplified the following from the dynamic-remotes example

const loadScope = (url, scope) => {
  const element = document.createElement('script');
  const promise = new Promise((resolve, reject) => {
    element.src = url
    element.type = 'text/javascript'
    element.async = true
    element.onload = () => resolve(window[scope])
    element.onerror = reject
  })
  document.head.appendChild(element)
  promise.finally(() => document.head.removeChild(element))
  return promise
}

const loadModule = async (url, scope, module) => {
  try {
    const container = await loadScope(url, scope)
    await __webpack_init_sharing__('default')
    await container.init(__webpack_share_scopes__.default)
    const factory = await container.get(module)
    return factory()
  } catch (error) {
    console.error('Error loading module:', error)
    throw error
  }
}

const RemoteButton = React.lazy(() => loadModule(
  'http://localhost:3002/remoteEntry.js',
  'app2',
  './Button'
))

Try using it in the basic-host-remote example (app1/src/App.js). It catches the ChunkLoadError I was having issues with.

I still don’t think we should have to drop down to the low level api to get proper error handling though.

Where you place try/catch, we don’t have magic for errors

what I want is to be able to protect app1 from errors in its remotes. There doesn’t seem to be any way to catch the ChunkLoadError and display some sort of fallback.

Without the ability to protect the host app the whole system is very fragile. It’s one thing if a new version of an npm package breaks something as you can detect that at build time, but with federated modules being pulled in at runtime any team developing any remote can take down the whole federated system without any notice if they deploy a bad build.

Not saying there shouldn’t be an error, just saying that errors should be catchable.

Also ran into this. The dynamic import promise should be rejected, since the chunk error should happen within the bounds of that promise.

I was trying to solve a similar issue where I wanted my container app to run even if a dependency was down.

I ended up using the import() function to import my dependency. My host app’s index.js looks something like this:

import('./bootstrap').catch(error => console.log('The dependency is down'));

With that your host should survive any issues with loading up the dependent service.