Building Microfrontends Part I — Creating small apps
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.
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.
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.
Before starting, you should have at least a little experience with:
- Node and npm
- 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
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 your
package.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
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:push web
You can see the running example here:
(all heroku links might take a while to load because heroku dynos go to sleep)
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:
You can also see them running:
And here are some pictures:
See how the styling is consistent?
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!