Micro frontend. Architecture Overview and Recommended Practices

The micro-frontend concept is a microservice approach to front-end development. The current trend is to create a powerful and feature rich web application that sits on top of microservice architecture… Over time, micro-frontend architecture becomes part of the application, often developed by a separate team. This architecture is growing and becoming difficult to maintain. A so-called “front-end monolith” appears. To solve this problem, the concept of micro-frontend was formulated.

The team is cross-functional and develops features in an end-to-end manner: from the user interface to the database. The micro frontend is clearer than a monolith and less cumbersome. A micro-frontend architecture of this type is designed to categorize all components of an application based on their business component, across the entire stack. In this case, front-end developers can count on the same degree of flexibility, testability, and development speed that is customary for back-end teams working with microservices.

How does a micro frontend work?

Front-end strategies, best practices, and recipes make it possible to build a modern web application that is developed by many teams that can use different JavaScript frameworks.

Here are the basic concepts behind the micro-frontend architecture

Technological independence

Each team must select and improve the stack without coordinating with other teams. Native elements allow you to hide implementation details while others provide a neutral interface.

Isolation of code generated by different teams

Never use the runtime together, even if different teams work with the same framework. Build an independent and self-contained application. Don’t rely on shared state or globals.

Creating command prefixes

In cases where isolation is not yet achievable, use naming conventions. Create namespaces for stylesheets, local data storage, events and cookies; this will avoid collisions and clarify who owns what.

Browser native capabilities are preferred over APIs you created

For communication, do not write a global publish / subscribe system, but use browser events. If you need to create an API for multiple teams to work together, try to keep it as simple as possible.

Ensuring reliable web design

All features should be useful, even if JavaScript fails. To improve perceived performance, take advantage of generic rendering and progressive enhancements.

What are the best practices in micro frontend

The various practices used to implement a micro-front-end architecture are:

1. A single meta-framework for SPA (single page applications) combines several applications on one page at once without the need to refresh the page; such are, in particular, React, Vue, Angular, etc.

2. Many single page applications are located at different URLs. For shared functionality applications, you must use NPM or Bower components.

3. Isolation of micro-applications in Iframes using Windows. API for sending messages and libraries are needed for coordination. IFrames share the APIs provided by their parent window.

4. Different modules must communicate via a shared event bus. Each module works with its own framework when handling inbound and outbound events.

Component libraries that depend on the main application stack, the various components and sections of the application are developed as libraries, after which they are “required” by the main application. Consequently, the main application consists of disparate components.

How to adopt a micro-front-end architecture?

Here’s how to migrate to a micro-frontend architecture and implement microservice testing using web components:

Browser integration

Web Components provide a way to create client-side snippets imported into web applications. These chunks can be packaged into microservices along with the back-end components. The created services are fully equipped with both logic and visual representations packed together. This approach reduces front-end applications to routing, making decisions about which set of components to display, and orchestrating events between different web components.

Web components

Web Components provide a way to create reusable units that are imported into web applications. They are like widgets imported into any web page. They are currently natively supported in Chrome, Opera and Firefox browsers. If a particular browser does not natively support web components, compatibility is achieved using JavaScript polyfills. Web Components are composed of 4 elements that can be used separately or together –

1. Own elements

2. Shadow DOM

3. HTML imports

4. HTML templates

Own elements

Using Custom Elements, you create your own HTML tags and elements. Each element is accompanied by its own CSS styles and scripts. If you need to create your own tags, apply CSS styles and add behaviors, then this is done using scripts. The only required standard is hyphenation to avoid conflicts with new HTML elements. For example, creating a checkout list that contains both native items and native tags results in web components and item lifecycle callbacks. These lifecycle callbacks allow you to define behaviors specific to component development. Lifecycle callbacks used with native elements are as follows:

1. CreatedCallback – defines the behavior that occurs when the component is registered.

2. AttachedCallback – defines the behavior that occurs when the component is inserted into the DOM.

3. DetachedCallback – defines the behavior that occurs when the component is absent from the DOM.

4. AttributeChangedCallback – defines the behavior that occurs when an attribute is added, changed, or removed.

Best example with custom elements:

class CheckoutBasket extends HTMLElement {

constructer (){...} is created

connectedCallback (){...}  attached to DOM

attributeChangedCallback (attr , oldVal , newVal)  someone changed an attribute

disconnecteCallback () {...}  removed from DOM, cleanup events that have been registered
}

Custom default elements – stencil, svelte, SkateJS, AngularElements, hyperHTML, etc.

Shadow DOM

Shadow DOM from the main DOM is an API that combines HTML, CSS and JavaScript inside a web component. When they are inside a component, they are decoupled from the main document object model. This separation resembles the following situation: the user is engaged in the creation of API services, and the consumer of the API service does not know anything about its internal structure, since all that is important to the user is API requests. Such a service has no access to the outside world, except for requesting the API of other services. Similar capabilities have been introduced in Web Components as well. There is no appeal to their internal behavior from the outside, except in cases where it is deliberately allowed. Likewise, the shadow DOM does not in any way affect the main DOM of the document in which the components are located. The main way web components communicate is by firing events.

HTML imports

For web components, HTML imports are the packaging mechanism. HTML imports tell the DOM where the web component is located. In the context of microservices, the service remote location import contains the component that you want to use. HTML imports allow you to reuse and include HTML documents through other HTML documents. Predefined components that act as HTML imports, each including their own styles and scripts, decide at the highest level what the HTML import currently represents in the DOM, and the imported document handles all other things.

  • A wrapper is the outermost wrapper, consisting of a container for a component and a palette of components. It should include controllers or views that allow the user to manipulate the components.

  • The container is the actual root point where the HTML code of the nested applications should be embedded. It must have a single entry point for all nested applications.

  • The Component Palette allows you to manage the nested applications that are currently active.

HTML templates

An HTML template is an element that contains client-side content that is not displayed on page load. Let’s try to understand the implementation of a micro-frontend architecture using the following application written in React.Js as an example. It is good when web applications are developed independently of each other, so that when some element changes, it does not block and damage others. That’s why, in this example, the new React app needs to be built, run, and deployed separately, and the other apps it needs to communicate with are treated as services. For example, the following example creates a header for a web page. React.js is used here. This is a newfangled thing. Let’s use create-react-app for fast bootstrapping:

npm install -g create-react-app

create-react-app head

cd head/

npm start

Now watch how quickly we can add server-side rendering. Later, this feature will help us with search engine optimization and performance improvement. It’s easier to attach this at the very beginning.

Next, let’s create a file called server.js in the root of the project; it will run the express server and also do the server-side rendering of react:

const path = require('path');

const fs = require('fs');

const express = require('express');

const React = require('react');

const App = require('./transpiled/App.js').default;

const { renderToString } = require('react-dom/server');

const server = express();

server.get('/', (req, res) => {

const htmlPath = path.resolve(__dirname, 'build', 'index.html');

 fs.readFile(htmlPath, 'utf8', (err, html) => {


const rootElem = '
const renderedApp = renderToString(React.createElement(App, null)); res.send(html.replace(rootElem, rootElem + renderedApp)); server.use(express.static(‘build’));const port = process.env.PORT || 8080;server.listen(port, () => { console.log(`App listening on port ${port}`); });

This script is rooted where the react (App) element is, renders it to a string, and sends it to HTML before serving it out to the user. Later, React will hoist up based on this already rendered component. But it works on NodeJS, and Node JS does not understand JSX or other relatively new types of syntax, for example, import, so babel was used to transpile this code before running it on the server:

npm install --dev babel-cli babel-preset-es2015

Add two tasks to the scripts section in package.json to run this:

"transpile": "NODE_ENV=production babel src --out-dir transpiled --presets es2015,react-app",

"start:prod": "NODE_ENV=production node server.js"

That’s all. Now we run the header with:

npm run build

npm run transpile

npm run start:prod

Why are micro frontends so important?

Nowadays, when new web applications appear, the client side is getting bigger, and the importance of the server side is decreasing. Most of the code is from the micro-frontend architecture. And the monolithic approach doesn’t work with large web applications. There must be a tool for breaking such a monolith into relatively small modules that operate independently of each other. The solution to this problem is a frontend microservice appliance. The client-side code is written exclusively in pure JavaScript and using any javascript frameworks from which or to which the migration was carried out.

What are the benefits of a micro-front-end architecture?

Every day, a new technology for JavaScript is being invented, and the number of these technologies is growing like a snowball. This can be frustrating at times, as each JavaScript technology has its own merits and demerits. And when choosing a technology, you always strive for maximum benefits and minimum risks. Recommended micro-frontend practices suggest that different technologies should be applied to develop different services. Here are just some of the advantages of such an architecture:

  • Support for code and style isolation. Each development team can choose the technology to their liking. Both development and deployment are very fast.

  • Promotes continuous deployment

  • Testing is greatly simplified; when you need to test a small change, you don’t have to touch the entire application.

  • Frontend Renovation – Make Cosmetic Upgrade Easier

  • Increased reliability and ease of support

Concluding remarks

You will see that in a micro-frontend architecture, both the core of the code and the integration are incredibly simple. One of the critical issues is the standardization of UI / UX principles. One-stop solution is to rely on style guidelines, among others Material Design, Bootstrap. For everything to work smoothly, you need to establish communication within the team, develop standards and rules, and minimize friction between different teams. All of these practices recommended in a micro-frontend architecture address a critical issue: scalability. There are applications that start to swell, and with such growth, numerous problems and conflicts are associated. If you divide the code between teams and properly organize its “logistics” – quality will come, technological trends will be taken into account, and the world will be enriched with new fast solutions.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *