DEV Community

Cover image for Setup a Micro-Frontend architecture in 15min with Vite!

Setup a Micro-Frontend architecture in 15min with Vite!

Meidi Airouche on December 10, 2024

In a monolithic frontend architecture, a single codebase handles the entire user interface. While this can simplify initial development, it can bec...
Collapse
 
ozzythegiant profile image
Oziel Perez

This is great for SPAs, but if you guys just want a traditional website with different frameworks for functionality, try Astro instead

Collapse
 
mairouche profile image
Meidi Airouche

When choosing between Vite and Astro for microfrontends, it depends on your project’s needs.

Imagine you're building a SaaS dashboard for analytics with microfrontends:

  • Real-time Data Visualization (React): Graphs, charts, and stats that update live via WebSocket or polling.
  • User Management (Vue): Complex CRUD operations with modals, forms, and validation.

Where Astro is Limited:

  • Real-time Interactions: Astro’s static-first model means it struggles with highly dynamic components like live-updating graphs or dashboards that need frequent re-rendering based on API data. You’d have to include several "hydrated islands" (Island Architecture oriented), which increases complexity and runtime costs as Astro initializes these components separately.
  • Complex State Management: Dynamic state handling (e.g., syncing data between user actions and server updates) is cumbersome in Astro because it isn’t built for full-fledged SPAs or highly interactive systems.

Why Vite Excels:

  • Dynamic Features: Vite handles WebSocket-based updates and dynamic rendering seamlessly, with frameworks like React or Vue fully supported out of the box. For example, a live-updating dashboard built with Vite remains performant and developer-friendly.
  • Development Speed: Vite’s Hot Module Replacement (HMR) ensures that developers can see live updates to components like charts or forms without a full reload, even when working across multiple microfrontends.
  • Interoperability: In the SaaS dashboard, you can mix frameworks (React for visualizations, Vue for forms) easily with Vite’s ecosystem and tools like Module Federation to manage independent builds.

Conclusion

Astro is ideal for static pages, but for the dynamic, interactive SaaS dashboard core, Vite’s performance, flexibility, and robust runtime support can make it a better choice.

Collapse
 
juststevemcd profile image
Steve McDougall

100% recommend Astro over anything else these days. Unless you need something specific from one of the other *kit frameworks

Collapse
 
mairouche profile image
Meidi Airouche
Collapse
 
florianrappl profile image
Florian Rappl

Sorry, but I don't see the "micro frontend architecture". There are some core properties that are unanswered (or maybe I could not see / find it):

  • The composition should be possible at runtime; but here everything is composed in one build step. In general this is possible (build-time composed MFs), but then
  • The sources must be able to come from different repositories (here its all in one repository)

Generally, if you look at things such as Module Federation, Native Federation, Piral, ... these solutions give you something that is distributed from the beginning, i.e., where you (by default) have runtime composition.

Having team autonomy (which is the most important aspect of a micro frontends architecture) is only possible with independent deployment processes. So how would I update, e.g., the trending module, without updating the whole application? How could I add another module without having to redeploy the application?

Sorry if my comment comes across negative - it is meant as an encouragement; not as a letdown.

Collapse
 
mairouche profile image
Meidi Airouche

Thank you for your comment! Every feedback is welcome.

You’re absolutely right that runtime composition and independent deployments are very important. My article primarily focuses on the get started, where modules are combined via dist directories for simplicity of the article and quick setup.

However, for production, Vite can indeed support runtime federation by leveraging:

  • Dynamic imports to load modules hosted on separate DNS addresses.
  • Shared dependencies using peerDependencies to avoid duplication.
  • Independent deployments, allowing teams to update or add modules without redeploying the entire application.

I’ll update the article to clarify that the dist approach is meant to onboard, while runtime federation is better suited for production. Thanks again for your valuable feedback, it helps make the article more complete! 😊

Collapse
 
mairouche profile image
Meidi Airouche

I added the bonus section to the article to explain how :) Thank you

Collapse
 
han_yang_20969b18accbe79e profile image
Han Yang

very good tutorial, but angular v19 do not have .\app\app.module.ts, in dist folder, vue generated header.umd.cjs file, react do not generate trending.umd.js.

Collapse
 
mairouche profile image
Meidi Airouche

I passed everything in ESM since it's more standard now. Thank you for the feedback <3

Collapse
 
han_yang_20969b18accbe79e profile image
Han Yang • Edited

current status - 2024-12-11 - base concept works fine

Image description

Thread Thread
 
mairouche profile image
Meidi Airouche

I added the repository with the overall code working (except for Angular) at the end of the article : github.com/mairouche/mfe-news-portal

Collapse
 
naveen_ravichandren_a7b58 profile image
Naveen Ravichandren

Thanks, this is kick-ass.
I have a doubt, how would u share data across these 2 components? Vue to react and vice versa

Collapse
 
mairouche profile image
Meidi Airouche

With Redux for state management for example which is accessible from Vue, React or even Angular.
With RxJS for cross-component events since it's also compatible with each lib/framework.

You can also have shared data in the Shell like following for example :

// shared/service.js
let sharedData = null;

export const getSharedData = () => sharedData;
export const setSharedData = (data) => { sharedData = data; };

// React Microfrontend
import { setSharedData, getSharedData } from './service';

setSharedData('Data from React');
console.log(getSharedData());

// Vue Microfrontend
import { setSharedData, getSharedData } from './service';

setSharedData('Data from Vue');
console.log(getSharedData());
Enter fullscreen mode Exit fullscreen mode
Collapse
 
juan_labrada_42e0d23118f4 profile image
Juan Labrada

Absolutely loved this post!!

Collapse
 
mairouche profile image
Meidi Airouche

Thank you very much <3

Collapse
 
griffinrivera profile image
Griffin Rivera

Thanks for sharing.

Collapse
 
farseenmanekhan1232 profile image
Mohammad Farseen Manekhan

This is amazing.
This is exactly what's happening in Astro behind the hood.
Correct me if I'm wrong.

Collapse
 
mairouche profile image
Meidi Airouche

To be Honest I discovered Astro with a previous comment and I'll deep dive into it. It looks like the same with Astro being maybe a bit more opinionated and closer to a framework than a library. But I'll look for it to see if I well understood

Collapse
 
mairouche profile image
Meidi Airouche

After deep diving into astro and trying it (only for 2 days so not that much background at this stage), this is what I conclude :
dev.to/mairouche/comment/2ka02

Collapse
 
kevinluo201 profile image
Kevin Luo

How does the router work in this case?

Collapse
 
mairouche profile image
Meidi Airouche

This is a good question. I was affraid that the article would be too long if I deep dived into routing, state, refs etc...

I'll answer here then.

In the Shell, you can use a vue or react router (what you prefer) to route to any kind of component. For example :

import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  { path: '/', component: HomePage },
  { path: '/vue-mf', component: () => import('vueMicrofrontend/App') },
  { path: '/react-mf', component: () => import('reactMicrofrontend/App') },
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;
Enter fullscreen mode Exit fullscreen mode

Once the microfrontend is loaded throught the global Shell router, it uses its own internal router if it has one.

So a good practice would be to keep the Global Shell router just load the micr-frontends and then, each micro-frontends having its own dedicated standalone router.

Collapse
 
mahmoudalaskalany profile image
Mahmoud Alaskalany

Thanks for this post i will try this with angular

Collapse
 
ciphernutz profile image
Ciphernutz

Absolutely agree with your points. This is a game-changer!

Collapse
 
hieu_buihuu_3fe912f1ad47 profile image
Kevin.CK

Thanks

Collapse
 
lwz7512 profile image
liwenzhi

Couldnt integrate angular app, got error:

Uncaught SyntaxError: The requested module '/apps/highlights/dist/main.js' does not provide an export named 'mount' (at main.js:3:10)

has anyone make it run successful?

Collapse
 
mairouche profile image
Meidi Airouche

Depends on the version. Try with this in src/main.js:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

function mount(el: HTMLElement) {
  const bootstrap = async () => {
    const appElement = document.createElement('app-highlights');
    el.appendChild(appElement);
    await platformBrowserDynamic().bootstrapModule(AppModule);
  };

  bootstrap().catch(err => console.error(err));
}

export { mount };
Enter fullscreen mode Exit fullscreen mode
Collapse
 
lwz7512 profile image
liwenzhi

got an abnormal main.js file under dist folder:

"use strict";(self.webpackChunkhighlights=self.webpackChunkhighlights||[]).push([[792],{429:(e,o,_)=>{}},e=>{e(e.s=429)}]);
Enter fullscreen mode Exit fullscreen mode

Do you mind sharing your full project code? this is really interesting...i have never seen a solution like this...

Thread Thread
 
mairouche profile image
Meidi Airouche

I update to last versions and share it tomorrow. I ping you in comment when it's done

Thread Thread
 
mairouche profile image
Meidi Airouche • Edited

@lwz7512 Indeed, I was using module federation with old Angular versions. I will find out what's the best approach between, widgets, module federation or web component and propose it in an edit of the article.

Collapse
 
connectionshint profile image
Connections Hint

Like it!

Collapse
 
mayur_athavale profile image
Mayur Athavale

Gr8 explaination and systematic approach. Got to learn a lot.🙌

Collapse
 
getsetgopi profile image
GP

Integrating multiple technologies within a micro frontend architecture is generally regarded as a suboptimal design choice. This approach can lead to significant performance issues, as it necessitates loading numerous technology libraries alongside each component, resulting in a bloated and resource-intensive application. Moreover, the complexity introduced by this multi-technology setup can make maintenance and management exceptionally challenging.

A more streamlined and efficient approach is to standardize on a single library or framework across the micro frontend ecosystem. This strategy offers several advantages:

  1. Improved performance due to reduced overhead from multiple libraries
  2. Simplified codebase that's easier to maintain and update
  3. Enhanced consistency in development practices and user experience
  4. Better team collaboration and knowledge sharing
  5. Reduced learning curve for new developers joining the project
  6. More straightforward integration and communication between micro frontends

By focusing on a unified technology stack, development teams can create more cohesive, performant, and maintainable micro frontend applications that align better with the core principles of this architectural pattern.

Collapse
 
mairouche profile image
Meidi Airouche • Edited

Agree. This is why I explained in the article that it can be a solution (temporary one) to shift from a framework to another smoothly here :

In a real life software growing through years, being able to handle multiple frameworks can be a smooth way to migrate from an old one to a new one whenever it's needed.

For example, in my experience, we transitionned form Angular to Vue step by step thanks to this approach. I'm not saying it's a desirable design but it's an existing one. Used in the appropriate context, it can bring value.

Collapse
 
sirserje profile image
Serhii Viazkov

did you have any luck with precious angular versions , eg 18?

Collapse
 
mairouche profile image
Meidi Airouche

I succeed with module federation from Angular 16- but it's not that simple. I'm still testinfg things but Vue and React are Libraries whereas Angular, as a Framework, has it's own event, state, data management etc... So it's not that easy.

Collapse
 
luoboding profile image
peng

i wonder how to manage route?