DEV Community

Cover image for Micro-frontends: Module Federation with WebPack 5

Micro-frontends: Module Federation with WebPack 5

Brandon Villa on August 07, 2020

What is Module Federation? It is basically a JavaScript architecture. It allows a JavaScript application to dynamically load code from a...
Collapse
 
vonwao profile image
vonwao

I still don't fully understand the big deal here. Couldn't you already load JS modules dynamically before by using the import statement? And you could already compose the separate modules into an app by using single-spa.js.org/

It seems the main advantage remaining would be using dynamic modules for SSR, but from what I heard Next.JS doesn't support module fedaration. :/

So what is actually the big idea? Looking at the webpack config above I'm concerned this new architecture is just going complicate things and also lock-me-in to webpack.

Collapse
 
scriptedalchemy profile image
Zack Jackson

Next supports MF, with some workarounds that I created. Next 10 will support MF as a flagship feature.

Single SPA doesn't make the JS payload smaller, it lets you mount many apps and bus data between them. Module federation is pretty much dynamic imports between separate webpack builds that are deployed independently. Single SPA also relies on system.js to share code. MF can support multiple versions if needed and has intelligent semantic versioning at runtime.

As for support, I've already released partial support for rollup and parcel will be adhering to our API interface. All three bundlers should be compatible with each other since we are working to make this interface universal. No lock-in.

Collapse
 
arshita04 profile image
Arshita Narayan

You have mentioned,that the support for rollup and parcel were released. Couldn't find the example which shows the support for parcel anywhere.
Also, how is module federation different from single spa.

Collapse
 
brandonvilla21 profile image
Brandon Villa

Hi vonwao. Actually the new thing here is not dynamically loading, as you said you could do this by using import() syntax. The new feature here is that with only a single plugin you have the capability to separate your JS code into different projects and work with them at build time, I don't think there will be much change in your Webpack config if it's only a matter of adding a Plugin pretty much :)

Not entirely sure if single-spa works at build time or runtime, which could be a big difference, but I see they are already experimenting with using Module Federation, the only downside I see for single-spa is that the setup looks heavier

People from Webpack are working with Next.JS to bring this feature btw: github.com/module-federation/modul...

Collapse
 
alexvukov profile image
alex-vukov • Edited

Thank you for this article! It was very useful since I am in the process of making use of federated modules in a large corporate MFE solution. There is one small problem in this new functionality though and that is cachebusting the remoteEntry scripts. In order to invalidate the cache for a remoteEntry script each time it changes you have to add a content dependent hash to its name. But then you have to somehow know the new name in order to import it into the shell application. This creates the need for an extra request to get the new name before loading the remote container which is inconvenient.

Collapse
 
joscluis profile image
JoscLuis

Obtengo un error al compilar la aplicación: npm run build
error:

12 0.726

12 0.726 > container@0.1.0 build /app

12 0.726 > react-scripts build

12 0.726

12 2.108 Creating an optimized production build...

12 8.336 Failed to compile.

12 8.336

12 8.337 Module not found: Error: Can't resolve 'app2/App' in '/app/src/modules/traking'

12 8.337

12 8.337

12 8.503 npm ERR! code ELIFECYCLE

12 8.503 npm ERR! errno 1

12 8.506 npm ERR! container@0.1.0 build: react-scripts build

12 8.506 npm ERR! Exit status 1

12 8.506 npm ERR!

12 8.507 npm ERR! Failed at the container@0.1.0 build script.

12 8.507 npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

12 8.514

12 8.514 npm ERR! A complete log of this run can be found in:

12 8.514 npm ERR! /root/.npm/_logs/2021-12-21T16_42_43_474Z-debug.log

Collapse
 
fburner profile image
FBurner

I have problems to understand if this is correct solution, the purpose of microfrontends would be not to be exposed to other but be selfcontained systems.

So the only problem that should have been solved is the loading of depencies and pushing the bundle to some application register.

With this it looks like you just build a distributed monolith?

Collapse
 
norbertb29 profile image
Norbert Bartos

Thanks for this post Brandon!

This is exactly what our current project needs to fulfill the requirements. We will have some (1-3) SPAs with N different modules everything on the same stack (React based) with separated CI/CD pipeline. These modules and SPAs will be developed by different teams and we will need to integrate these modules into the given SPA.

I am just thinking about this new feature and I am not sure if I correctly understood it. I don't really see the differences between this plugin and my concept. For example we can integrate separately built and deployed app modules into the "parent" SPA with the current tools already (at least we can do it by authoring webpack libraries and loading them into the SPA so we can control the module lifecycle by using React DOM to mount/unmount it into the given SPA's DOM container element).

What will be the benefits of using Module Federation?

Is this what solves the described problem with more elegant way? I see that this could optimize the bundle sizes by sharing the common dependencies. In the example you are lazy importing the exposed Counter component directly, but I assume type inference will not work, because it's not in the same module like we would do in monorepo setup. Am I missing something?

Collapse
 
deexter profile image
deexter

What if my MF accepts some props?
Is there possibility to expose types for typescript?
Or is this bad practise and MF has to be without props?

Collapse
 
plsfix profile image
PLSFIX

Nice article, thx!
Is it correct both apps have the same port?

publicPath: "http://localhost:3000/",

Collapse
 
brandonvilla21 profile image
Brandon Villa

Thanks for your comment, actually it should be a different port. Good catch! I'll update the post :)