Reimagining Our UI: From Utility to Core Component
Recently my team started thinking about replacing our UI in our system. The core of our system consists of several modules that ingest, process and publish data from GPS trackers. Historically, UI wasn't a core context in our system; it functioned as a configuration and observability utility for developers and a few end users. You could remove it, and the system would still work and generate value. Over the years, UI context gained importance. We now want to modernize it and align its design with other applications.
Considering Context Ownership in UI Development
One of the considerations that we are debating is if we can make context own parts of the UI concerned directly with it. For example, can we make context dealing with signal sources publish UI concerning its configuration? We can accomplish that by making our UI context a shell for micro frontends published by different contexts. To make UI consistent across all micro frontends, we could build a design system published and consumed by them.
Proving the Concept: A Step-by-Step Approach
This post will detail the PoC I've built to prove the viability of this approach. It will consist of the following steps:
Building a design system - a react component library that can be reused across different micro frontends. We will use tailwind as a seed for our design system. We will configure the storybook for testing and documentation. We will export it as a package.
Consuming design system in micro frontends. For all build and packaging needs, we will use webpack 5. We will give micro frontends the ability to display as a standalone application or embedded in a shell application.
Composing micro frontends in a shell application.
To make examples more relatable for readers, we will change the domain. Somehow equivalent to our situation would be building an application for improving fitness and wellness. We can imagine an application like this would consist of the following contexts: nutrition tracking, exercise tracking, meal planning and recipe management. Each of these contexts could live independently; however, it will generate additional value when combined.
The goal of this PoC is to have 4 micro frontends, shell application, and storybook (design system) run on separate ports. As on the screenshot below.
We should be able to run all micro frontends composed in a shell application and separately in stand-alone mode. Additionally, storybook, documentation for our design system should also run separately.
Access the Source Code
You can find source code for the final solution in this repository https://github.com/belczyk/blog-examples-desing-system-mf.
Exploring Different Approaches to Micro Frontends
Before we jump into the code, let me say that this is not the only approach for micro frontends and design systems that you can choose. For example, instead of agreeing on one frontend framework and publishing components, you could publish only style sheets/design tokens and allow teams to select the frontend framework that they want to use.
There are different ways you can integrate your micro frontends. We will explore only one way (via JavaScript inclusion). See the "Micro Frontends" blog post on Martin Fowler's blog to explore options.