Building Microfrontends Part I — Creating small apps

Introduction

When your front-end starts getting too big, you will want to split it in smaller parts and give each part to a different team to develop, but at the end, they all need to integrate somehow in the same front-end so the user can see it.

This blog post series was built on top of the thoughts produced by Zalando’s Project Mosaic, Open Table’s Open Components and my own experience.

The goal of this series is to be a hands-on guide for creating a Microfrontend Architecture from scratch, at the end you will have 5 containers running, with apps communicating with each other in an architecture that allows scalability.

Most of the time, I’ll be referring to web development here, but maybe those ideas also apply to desktop apps (like spotify's) or mobile apps. If you have more experience with those, please let me know.

Also, as you will note along the way, this is not only a technological problem, but also a communication one. Teams have to communicate well with each other in order to get this kind of architecture working, but I'll focus more on the tech part of it.

Vocabulary

Before we start, let’s establish some vocabulary, for me an important distinction when breaking the front-end is between apps and components.

The difference between an app and a component has nothing to do with the amount of code it has, I like to put it simple: apps don't depend on others to live, while a component can only work within an app.

For example, the header of your website, which probably has the menu and logo, is an app, because the user can see it and use it even when other parts haven’t loaded. But a datepicker is a component, because it doesn’t make sense for a datepicker to live by itself, outside an app, even though it could have thousands of lines of code more than a header.

Assumptions

Before starting, you should have at least a little experience with:

  • Node and npm
  • Docker
  • React and its environment
  • NodeJS and Express
  • Heroku (or any other way to host a docker container)

Building a small, self-contained app

It is good when your app can evolve independently, you will want to introduce changes without being blocked by others and without breaking others as well. That's why we need to create an app that can be built, run, and deployed separately, treating others that has to communicate with it as services.

Our first app will be a header for our page. For this example we will use react, because why not? All the cool kids are using it nowadays. Let's use create-react-app for fast bootstrap:

npm install -g create-react-app
create-react-app header
cd header/
npm start

After that you should already have a full-blown react app.

Now let's add server-side rendering real quick, we will need it when joining apps later, for performance and SEO reasons. It is easier to add this at the beginning, where we are, than latter.

First, let's change our src/App.js to look like an actual header:

Then, at the root of the project, create a file called server.js, that will start an express server and server-side render react for us:

So, to explain very quickly, this script takes your root react element (App), renders it to a string, and shove it into the HTML before serving it to the user. React will later mount on top of that already rendered component.

But, that runs on NodeJS, and NodeJS doesn't understand JSX or other newer syntaxes like import, so we need babel to transpile it before running the server:

yarn add --dev babel-cli babel-preset-es2015

Now you just need to add two tasks on the scripts section of yourpackage.json to run that:

"transpile": "NODE_ENV=production babel src --out-dir transpiled --presets es2015,react-app",
"start:prod": "NODE_ENV=production node server.js"

That's it, you can now run the header with:

npm run build
npm run transpile
npm run start:prod
What? Of course we need React just for that!

Cool, it works! But probably just in our computers where we have node and npm well configured. In order to pack it to run elsewhere, let's use Docker, the cool kids are also using it!

On the root of your project, create a Dockerfile with this:

Then you can run your app inside docker by using:

docker build . -t header
docker run -t -e PORT=8080 -p 8080:8080 header

Now your app should be running inside docker, cool! Let's deploy it.

We can use good old heroku for that, since it now accepts Docker. You may also deploy it anywhere that accepts Docker containers.

Before deploying to heroku, start a git repo in your project with git init if you haven't already, commit all the files and then:

heroku create microfrontends-header # choose a different name
git push heroku master
heroku plugins:install heroku-container-registry
heroku container:login
heroku container:push web
heroku open

You can see the running example here:
https://microfrontends-header.herokuapp.com/
(all heroku links might take a while to load because heroku dynos go to sleep)

Beautiful.

If anything went wrong, you may check the final code here: https://github.com/microfrontends/header/tree/part-i

Two more apps

Let's create another two apps, the first will be a products list, and the second a cart. Just follow the same steps that were used to create the header and… done! You can clone them from github:

https://github.com/microfrontends/products-list/tree/part-i
https://github.com/microfrontends/cart/tree/part-i

You can also see them running:

https://microfrontends-products-list.herokuapp.com/
https://microfrontends-cart.herokuapp.com/

And here are some pictures:

See how the styling is consistent?

Next Steps

Now we have a bunch of apps in the wild, but we still want to join them in a single page for our website, on the next article of this series we will focus on that.

How is it going to work? iFrames? WebComponents? On the backend? You have to read it!

Go to part II.