Micro-frontends & SCS

Micro-frontends & SCS

  • micro-frontends
  • scs
  • performance
  • architecture
published 2020-09-15

It’s safe to say that frontend development has gotten pretty complicated over the years, even though I consider myself to be reasonably up to date with modern tech stacks, I’ll be the first one to admit that I’m far from an expert in a lot of it - nor do I strive to be.

If we take a look at some of the things we come across - like Docker, React, Preact, Vue, Svelte, Typescript, Linters, testing libraries, Storybook, Redux, Recoil, Tailwind, CSS in JS libs, Flutter, React Native, Expo, Webpack, Rollup, Express, Koa, GraphQL, Apollo, URQL, ORMs, Next, Gatsby, Sapper & plain vanilla JS you quickly realize that stating something other than what I wrote above is simply impossible. Nobody knows everything (...except full stack devs ofc).

Luckily, adding micro-frontends to the mix doesn’t necessarily require you to learn a new framework or a library, or that you need to stop using any of the libraries above.

But what it does ask of you is that you rethink how you look at frontend development and that you let go of the typical control associated with monolithic frontends.

In return, together with SCS you end up having options you didn’t have before, some being:

  • Being able to scale to multiple teams, each being independent and owning their own SCS.
  • Having autonomous release cycles per team - no more big bang releases.
  • A way to opt out of the current frontend refactoring meta taking place every other year.

In this post I’ll talk about what micro-frontends are, why they don't necessarily have to be complicated, and how they can open doors that are otherwise closed within monolithic structures.

What are micro-frontends and why now?

Micro-frontends architecture is the adoption of micro-services extended all the way to the UI layer. Other typical characteristics are that they’re built vertically, owned by dedicated cross-functional teams and that they span from the database to its interface.

Due to the nature of our ever-changing frontend eco system, micro-frontends offers us the option to independently invest in certain key areas of our UI and to optimize throughput by grouping the right people together.

So why now? why are micro-frontends getting popular 2020? I think that one answer is that frontend development right now has gone full circle, from our main line of business being dressing things up and making HTML look good, to the age of preferring CSR (client side rendering) and now back to acknowledging that rendering on the server / serving static content is good.

Assumed disadvantages = advantages

Some of the general skepticism of micro-frontends comes from what I believe are misguided assumptions, where the contrast of wanting to build something like we've always have, to actually working towards the end goal of breaking up a monolith into smaller decoupled UIs, can easily lead us to perceive design advantages as disadvantages along the way - I’m referring to:

How do we deal with global X?**

  • Global styling,
  • Global state,
  • Global common code
  • How can we make a unified experience in terms of UI / UX
  • And what about DX?

All of these "pain points" are actual benefits in a micro-frontend architecture, so let’s go left to right and address each problem area with its simplest, most naive solution.

But first - context:

A team's journey towards SCS and micro-frontends


Let’s say we have a larger team of people working on a monolithic frontend / backend, the end product is a food app made as a node powered isomorphic React SPA.

Having had issues for quite a while regarding the ability to scale and deploy, and their CTO fresh back from vacation reading Team Topologies, they decide to dive head first and adopt SCS and micro-frontends, resulting in changes made to the current team structure - now divided into two separate teams with clear responsibilities:

Team A

In charge of the start page which contains all products

Team B

In charge of the checkout page, but not only that - they’re now also in charge of the cart shown on the start page.

As an effect to these changes, their isomorphic SPA has now been chopped into two separate projects (repos), both now with independent CI/CD setup and there’s something in front handling routing between the two, laying the ground for everything to still behave like it used to.

Suddenly, with doubled costs and their main React competence jumping ship, they collectively decide to sunset isomorphism and serve views using EJS / Razor or some other view engine on the server (or static).

Some devs in team B panic at first since they're the team owning the more complicated checkout application with behavior. But they keep their cool when they realize they could move logic to the server and progressively enhance client side.

Things are going great, but they do have som some valid concerns...

Nr.1 - Styling

The checkout button used to be the same component as the buy button, how can we achieve the same level of visual consistency across frontends? and what base styles and media queries?

Buttons - copy the markup and CSS, achieving visual consistency is only a challenge if there is something hindering the teams from communicating properly. Base styles and media queries are infrastructure and should reside in some kind of baseline (CDN).

Nr.2 - State / interactions

How do we work with global events and optimistic UI changes now that we don’t have a global state store like Redux?

The same thing can be achieved dispatching custom events.

document.dispatchEvent(new CustomEvent('name', { detail: 'payload' }));

document.addEventListener('name', eventHandler);

Nr.3 - Global utils / Shared infrastructure?

How do we solve common code / utilities ? I’m helping team A do X and I already have that in team B's repository.

I would say - tell yourself that D.R.Y is dead and start by duplicating X. Adding X to the common baseline is opening a door that you want to have closed. Chances are you'll start adding more and more things to it, and in the end building a frontend library that your teams are dependent of.

(D.R.Y stands for Don't repeat yourself)

General rules regarding the baseline infrastructure:

  • CSS base and media queries.
  • Typography.
  • Polyfills.

Nr.4 - Sharing components

We now need to find a way of delivering a mini cart to team A and possibly other teams, how should we approach this?

Let's answer that with the next segment - fragments.


Fragments

Fragments are composable UIs available through Server Side Inclusion (SSI) using Edge Side Includes (ESI) or Client Side Inclusion (CSI) using h-include. They are dependent of their own HTML, CSS and JS (optional) and are what teams produce / consume to enrich their pages.

No dependencies to the consuming environment

It's important to remember that your fragment needs to work on any host without needing anything from the host. Achieving this is crucial for the composition strategy, e.g a fragment containing an icon cannot assume that the hosting environment will provide that icon. Instead it should include the icon itself as an inline SVG. Same goes with text, css and behavior.

Caching & versioning

It's the fragment producing team's responsibility to own the resources of the fragment (versioning) and its caching strategy. The consuming micro-frontend doesn't care, or doesn't need to care about cache busting since that's handled by the provider.

Transclusion - Server side vs client side

Having two separate ways of working with fragment composition enables you to optimize for performance by using ESI and long cache strategies on the server and CSI for personalization / lazy loading on the client.

In short, all of this means that team B, the one owning the checkout page, now have a way of exposing their cart as a fragment.


summary

Knowing when to opt in or out of an architecture can be hard, and like with everything else - micro-frontends also have downsides as they introduce redundancy and costs associated with running x per team (stacks / ci pipelines etc...). This is something to be aware of although it's generally considered that these costs are worth it and cheaper than the cost of maintaining monolithic ventures over time should you want to invest in micro-frontends & SCS.