When people hear “microservices,” they often think exclusively about backend development. However, the frontend can also use such architectural style, leading to exciting innovations in web application design. Microfrontend architecture is an approach that extends the principles of microservices to the frontend by breaking down a monolithic frontend application into smaller, independently deployable fragments, that teams can develop, test, and scale features more efficiently.
Let’s take a look on what is the main differences between microfrontend and monolith architecture styles?
Monolith | Microfrontend | |
---|---|---|
Structure and Modularity | The application is built as a single | Applications are divided into smaller, independently deployable components |
Development and Deployment | Any changes require redeploying the entire application | Teams can use different technologies and frameworks for different components and deploy them independently |
Scalability | Scaling typically involves scaling the entire application | Different parts of the application can be scaled independently based on demand |
When should you consider using microfrontend architecture?
The most common case for using microfrontend architecture arises when your application is too big, complex, and has many independent components. In such scenarios, a monolithic frontend can become unwieldy, making it challenging to manage, update, and scale.
What are most popular integration methods?
Build time integration
During the build process, microfrontends are bundled together, and dependencies are resolved, resulting in a single deployable artifact.
Pros: it simplifies deployment since the final product is a unified application. Also, it is easier to manage shared dependencies, as everything is resolved during the build phase.
Cons: lefts less flexibility for teams to adopt new technologies or make changes independently, as all microfrontends are tied to the same build process. Potentially has longer build times as the application grows, making it less suitable for larger, complex systems.
Server-side integration
The server fetches the required microfrontend components and integrates them into a single response. This can include server-side rendering (SSR), where HTML is generated on the server for improved performance and SEO.
Pros: shows faster initial load times, as the client receives a fully rendered page. Improved SEO, as search engines can crawl the server-rendered content more easily.
Cons: has increased complexity in coordinating between teams for shared data and rendering logic. Potential latency issues if multiple microfrontends are fetched in sequence.
Run time integration
Short description: microfrontends are loaded as needed, often in response to user interactions or routing changes.
Pros: adds flexibility in using different frameworks and technologies, as each microfrontend can be developed independently. Moreover, it reduces the initial load time since not all components need to be loaded at once.
Cons: has increased complexity in managing shared dependencies and ensuring consistent user experiences across microfrontends. May have potential performance issues if not optimized properly, as multiple network requests may be made.
We will provide example of runtime integration configuration using React.js and Webpack 5 with Module Federation.
For such purpose we should have 2 separated react applications with webpack. Minimal package.json configurations should look like these:
"dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0" }, "devDependencies": { "@babel/core": "^7.15.8", "@babel/preset-react": "^7.14.5", "babel-loader": "^8.2.2", "html-webpack-plugin": "^5.3.2", "webpack": "^5.57.1", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.3.1" }
For the remote apps, in our case second app, we configure “plugins” section of our webpack config like this:
plugins: [ new ModuleFederationPlugin({ name: "second", // Name of the microfrontend filename: "second-app.js", // Name for remote connection exposes: { // List of exposed components "./App": "./src/App", }, shared: { // List of shared dependencies "react": {singleton: true}, "react-dom": {singleton: true}}, }), new HtmlWebpackPlugin({ template: './public/index.html', }), ],
NOTE: you should configure port different from main app, for example 3001.
For the main app, in our case the first one, we configure “plugins” section of our webpack config like this:
plugins: [ new ModuleFederationPlugin({ name: "first", // Name of the microfrontend filename: "first-app.js", // Name for remote connection exposes: {}, // List of exposed components remotes: { // List of remote entries "NAME@URL/FILENAME" Second: "second@http://localhost:3001/first-app.js", ... // Here can be other microforntends }, shared: { // List of shared dependencies "react": {singleton: true}, "react-dom": {singleton: true}}, }), new ExternalTemplateRemotesPlugin(), new HtmlWebpackPlugin({ template: './public/index.html', }), ]
Now we can add to our main app our second one like this. NOTE that lazy loading is very useful for us because of dynamic imports. This allows to load apps only when user needs them.
const SecondComponent = React.lazy(() => import ("Second/App")); export default function () { return ( <Suspense fallback={<div>Loading...</div>}> <div> <SecondComponent /> </div> </Suspense> ); };
And this is it! So now we can use our separated second app from the first one on the 3000 port.
Conclusion
Microfrontend architecture has proven invaluable in improving the scalability, maintainability, and performance of web applications. By dividing a large project into smaller, independent components, platforms can deliver a more responsive user experience with faster page load times and reduced development bottlenecks. This modular approach is also used in ConnectyCube and not only allows teams to work on individual parts of an application simultaneously but also enables uninterrupted integration of new features and technologies as they evolve. Ultimately, microfrontends pave the way for creating reliable and flexible applications that can adapt to changing user needs and project demands.
Excited to build your next app with microfrontend architecture?
ConnectyCube simplifies app development with robust, well-documented APIs and SDKs for multiple platforms. Our platform lets you seamlessly integrate chat, voice, and video features into your app, whether you’re creating a social platform, a communication tool, or something entirely new. With detailed documentation and code samples, we support you at every step.
Sign up today and start building with ConnectyCube’s powerful backend services.
Let’s bring your app idea to life together!