Story behind Micro Frontends in Sabre

Kamil Thomas
8 min readJan 23, 2020

--

Hello, I’m a software architect at Sabre and I would like to share with you my long journey with Micro Frontends. How it started and where we are after over 1 and a half year.

Sabre is a big player in travel tech market for decades. Part of our work is to build software, web applications. We build them for airlines, airports, car rentals, hoteliers, travel agents etc. For last ~2–3 years my focus is a hospitality department. What do we do there? Many things. One of them is building booking engines. We have a SaaS booking engine, custom booking engines, booking engines for travel agents and call centers and few more. But first things first.

So what is a Micro Frontend?

I already see that there are multiple definitions of what micro frontends are and how to create them. At this point I will only show you our/my vision. So… lets start with a short introduction.

The current trend is to build a feature-rich and powerful browsers apps. In many cases they sits on top of a micro service architecture. Over time the UI layer grows and gets more and more difficult to maintain. We can call it a Frontend Monolith. The idea behind Micro FrontEnds is to think about a website / web app as a composition of features. Each of them is responsible for one particular action. Simplifying you can have a one variation of a nice toy castle or you can have a box of lego bricks and build x number of castles, houses, cars etc.

How it started?

Around 2 years ago there was a big initiative in our hospitality department to integrate more security in our applications. Goal was to have a two factor authorization implemented everywhere. Good luck with that.. Don’t get me wrong. Most — if not all — of our new apps are React based. If we target only them I would simply create a React component we can reuse everywhere. Case closed. But no — it’s never that easy. We have multiple legacy stuff we need to support as well. .NET, Java, Backbone.js, jQuery.. . Every team started estimating their effort of implementing two factor authorization in 6 different ways. This includes:

  • multiple code bases to maintain
  • multiple efforts to test it

Now — let’s say someone will find an issue with a component. Or there will be services change. Every effort to resolve it or upgrade it needs to be multiplied.

At the end of a day overall estimation for all our web applications were thousands of hours.

So I said — give me half of that money and I will figure out a solution for that ;). I never got that money.. But honestly I never asked :).

At the back of my head I remember reading about a library that is simplifying a process of creating web components from React based apps. It was either on JS weekly newsletter or echojs. This library is Hybrids [https://github.com/hybridsjs/hybrids] So — I decided to create 2 React NPM packages:

  • Login component — you know, username and password, forgot password, handle all the validations and services exceptions. Return a token on successful login.
  • 2FA component — take a token and validate if it requires 2FA, if user is enrolled display validation options (push notification, enter a code, SMS, phone call) or do a step by step enrollment for a new device.

And create two entry files. One for a React and one for a Web Component version. React is simply a reference to a component container:

import LoginContainer from './login.container';export default LoginContainer;

Web component from the other hand:

Initially I compiled it using webpack and published them in our internal NPM repository. Guess what? It worked! Even on IE11 with few polyfills. Everywhere — .NET, Java, React.. . It was just a beginning! I didn’t want to add any extra technical details as this was my first implementation that was greatly improved. Stay with me here and I will show you what I started here.

What was next

So I proved that this approach is working. I saved thousands of hours. Now it’s time to prepare a strategy the whole organization can follow. Remember the part where I mentioned we are building lots of booking engines? I thought that building 2FA component multiple times is a waste of time. But it was merely a flesh wound. Try to imagine building:

  1. Hotel list
  2. Hotel details
  3. Hotel availability calendar
  4. Room / Rate list
  5. Room and rate details
  6. Reservation details
  7. Ancillary list and details
  8. Guest details
  9. Guest and payment form
  10. …..

Over and over again. New customer wants a new booking engine? Let’s build it. From scratch. Hey — someone wants a custom call center app — let’s build it — from scratch.. Now I should quote a Samuel L Jackson — enough is enough.. . But I think a definition of insanity will be a better choice.

Decision — time to start building reusable components! Here is a list of our requirements:

  1. Each component should work independently
  2. Reuse it in any kind of an application (Java, .NET, React, Vue, ..)
  3. Easy way to connect them with each other
  4. Easy way to restyle them
  5. Super flexible
  6. Support INTL — internationalization

As an example I will use a — surprise — a booking engine first page. Product availability.

On this page alone we can have a:

  • Navigation component
  • Calendar component with availability and prices
  • List of rooms with rates
  • Reservation details

I will deep dive into two components:

Navigation component

This one is simple. Not services connectivity. Just show guest selection. Support some configuration keys and have a callback method on search.

As you see a main difference between React and Web Component version is that we are not passing a method but a name of a method. When I am initializing a component in Hybrids I simply do a:

const onSearchMethod = window[onSearch];

When use change an occupancy we can do two things. Either we update attributes in product list component:

And when attribute is change a component will know that he needs to refresh a list of products. Or we can do this using events. Inside a navigation component we do a:

And in product list component we simply listen for an event:

Product list component

This one based on attributes is fetching products from our microservice returning available products per hotel.

Apart from obvious attributes required for a service to fetch a product you can see a:

  • api — it’s an API key. Whenever we have a micro frontend that is communicating with services we are first validating if API key exist, if it’s active and if our customer has an access to this widget / service.
  • hotel / chain — we require a hotel ID and chain ID to know for what hotel we are fetching a data for.

Technical details

Repository folder structure

I decided to go with mono repo. We keep every micro front end in one place. It make sense to have a separate repository for a big UI app but when you have a multiple small applications why not to keep them in one place?

As you see we are using rollup for building distribution file. It’s great and simple. We maintain two different configuration files. One for React one for a Web Component.

Bundling — Rollup configuration

Reason why we have a rollup configuration per micro frontend is that sometimes we require extra rollup plugins (json, svg). And reason why we have one for React and one for Web Component is because of different outputs. For React it’s basic:

React

Output is ES and CJS version. Separated styles in CSS file.

Web Component

Here I’m doing a small trick. As you may know the web component bundle is including all JS libraries. In case of React you are simply importing a component in your parent application and component is using peer dependencies. Size of a component is small because all main libraries are not included. In case of a web component we are adding React, Lodash, moment, … . And because of that size of a distribution file is big. That’s why we are creating two bundles for it. One with all libraries included — in case someone is just using one component. And there is a version without libraries. Just a source code included and customer need to make sure to add i.e. scripts from CDN to the website.

Styling and customization

My approach is a “bootstrap” approach. We have an internal CSS library and we are simply reusing class names across Micro Frontends. When we prepare a custom styles for a customer (different spacing and colors) we just generate a custom “bootstrap”. In case we have a more demanding customer we do overrides. Every component has a unique class names so it’s easy to adjust a component for most demanding customers.

Regarding customization — first rule is to make every component super flexible. Lot’s of configuration props. My newest idea is to customize HTML as well. In example we have a best price component that is fetching a best price for a hotel and displaying it. And this component has a prop:

So not only CSS is customizable, not only configuration but also a HTML.

Conclusion

It’s worth it. We manage to save a lot of hours and we created a new product we can sell to our customers. Not only huge applications but small widgets. Now instead of paying for a full booking engine you can create one yourself — from lego bricks. And customize it in a way you can imagine. Because at this point imagination is your only limitation (and data from services ;)).

Oh — and here is a sample app I created with a storybook included so you can start your own micro frontends library in no time:

https://github.com/jaing/micro-frontends-sample-app

--

--