Module Federation

DHH just wrote an interesting blog post about a potential future of web app dev without JavaScript bundling or transpiling.

Makes me think of two things I just recently learned about webpack 5 module federation and micro-frontend.

Like DHH was saying, there’s not a penalty for lots of script requests with HTTP2, seems like this is a direction front-end architecture is heading… instead of SPA, every component is a module fetched and cached individually…

Any plans on Meteor adopting webpack 5 module federation? It seems like tree-shaking on steroids.

1 Like

I also have read the article from DHH and I have a few comments on it.

About HTTP2 and sending modules individually, Meteor dynamic imports are very superior than other solutions for dynamic imports as we already do exactly as he explains, we already send the modules individually and invalidate the modules only when they have changes, the same idea explained by him to use with all files is already applied by Meteor in all dynamic modules.

Most of my personal apps everything except the home page, login page and main feature page are imported dynamically because of that so the initial bundle is pretty small and every dynamic module is cached individually exactly as explained by DHH.

This article is a nice wrap up for the future but Meteor already has features that we could expose better, like dynamic imports, that shows how ahead we were and we still are in some directions.

He also highlighted Webpack as the solution back in the days and Meteor was solving the same problems at the same time and without requiring any configuration at all, and we continue to offer many features without configurations.

And the part he explains about import maps we don’t need these as Reify interprets the imports already any way so we don’t need to worry about this part.

Meteor also handles the cases for old browser and new browsers, without any configuration, that will always allow Meteor developers to use latest features of ECMAScript event when they are not supported in all the browsers yet and avoiding polyfills when they do. What he said in the article is true for old features of ECMAScript but not for every new feature introduced in ECMAScript in early stages as each browser will always implement in a different timing and it’s very hard for developers to keep track of everything as we usually use only one browser personally.

Now responding to your comment specifically, I don’t see where SPA is going against individual modules, as I said above, Meteor is already doing this for SPAs for years.

I don’t have strong opinions worth sharing about module federation yet so I prefer to wait here. But it seems to be very similar to our dynamic imports as well, the only different is sharing between apps what I’m not so sure it’s a good idea.

And I don’t want to say by any means that Meteor is perfect and ready for all these cases mentioned in the articles and in your comment but I’m just highlighting many things that Meteor already has to solve the same problems.

The last optimizations made on Reify are probably going to open many doors for explorations.

We are also studying many tools to use in our bundle/build process, we are probably going to share some of that soon.

4 Likes

Filipe,

How do dynamic imports work with Cordova ? Do they get merged in the main JS file or can they be imported/downloaded dynamically/cached somewhere else in the app as a ressource ?

We have a problem where our cordova bundle is getting too big to load on older iOS devices (around 8mb, it just does not load and we get a nice blank screen). And the HCP gets too big at the same time.

Regards,
Burni

Hi, from the top of my head I would say it’s mixed in the bundle but there is a way to optimize startup that I usually use on my Meteor apps.

The way is to use nested imports so your bundle is not going to be a problem as the modules that are not necessary in the first page of your app are not going to be evaluated if you use nested imports on them. Nested imports feature is available only in Meteor as TC39 didn’t go forward with it, so it is a very nice feature that only Meteor users can use today.

This is a nice post about Nested Imports from Zodern: Nested Imports in Meteor

I know for sure that this approach works as I already implemented it in a very big app and it caused a huge difference in the load time of the app :wink:

The best way to select which modules you should start importing in this way is analyzing the CPU profile of your app in the client, you are going to see Reify loading the modules and you can see which ones take more time to be evaluated.

BTW, Reify will load modules much faster starting from Meteor 2.4 but I still believe Nested Imports are still useful as it is going to help avoiding the evaluation of many modules.

If you need more details on how to implement it let me know.

Another option for the future would be to also fetch code from dynamic import dynamically in Cordova but it would be better for the user to already have everything coming from the store, right?

1 Like

Hi Filipe,

Very interesting. I’m a bit confused between lazy imports and nested imports!?

I’m not sure when each should be used exactly.

Regards,

Burni

Dynamic Modules (lazy imports)

Dynamic modules (lazy imports) should be used when we want to avoid adding this module to your initial bundle, specially on Web.

In Cordova maybe this is not an issue as the user is expecting to download a few MBs from App Stores.

Nested imports

Modules that are nested imported (imported in a nested level of your code, inside a block) are going to be part of your initial bundle, so your initial bundle size will grow because of these modules but when your Javascript app starts in the browser it’s not going to evaluate this code.

This means your app will start faster as it is going to evaluate less code, this has a big impact if you evaluating big modules, for example, momentjs. So you are going to evaluate momentjs when you need it and not when your app is just starting.

This is specially important in Native Apps as some smartphones don’t have a lot of CPU resources and it could cause some slowness in the initialization of your app.

Conclusion

You should use both together, specially if you have Native Apps produced by your Meteor code.

Dynamic imports should be used where the module is not really important for the main user flow in your app and nested imports should be used when you know the module (or library) that you are importing are huge and they are not necessary in the first loading.

For example, in a React App lazy load every component inside your Route except your home page and login page. And also nested import any huge module, like your collections if you are using mixins and a lot of add-ons that make them huge and initialized in a single-shot.


But always remember, you don’t improve what you don’t measure, so use Dev Tools first to understand where are your bottlenecks. CPU profile is very helpful to find modules that take time being evaluated and Network tab is helpful to find modules that are huge.

1 Like

Felipe @filipenevola,
Could you explain more about how you work with MF in the Meteor ecosystem? i need to implement a resilient way to render my react micro frontends in a Meteor application.

AFIK Meteor doesn’t support the micro frontend architecture. When we were asked a year back what we wanted to see in Meteor in 2022, I asked for MF :).
I ended up using Iframes and authenticate via a secure cookie that the app which consumes it has to re-authenticate the cookie on the server side. I also use React.

Micro frontends usually answer two issues:

  • team, separation of interests/duties . In React this can be solved with multiple Switch/Routers adding multiple apps built over the same code base (with dynamic imports indeed).
  • complexity, weight of code - The only solution I found so far was using secured Iframes.