Sharing server code between micro frontends
At Wehkamp, we are moving our monolithic site into micro frontends. We started with the back end and rebuilt the front end as a single site. This turned out to be a problem. Different teams wanted to deploy new features at different times.
To solve this problem, we decided to split the front end as well, into micro-sites. We build each micro frontend in React, running on NodeJS inside a Docker container. We started by building a template site and copied that each time we needed a new micro frontend. After a while, each team would add improvements to their micro frontend. But these improvements didn’t make it back to the template site (or other micro frontend).
This was not a maintainable way of building these sites. There were two main problem areas: the base React components and the NodeJS server. A shared component library solved the first issue.
For the server, we started with extracting the server code to a separate npm package. The package takes care of several things:
- set up the Express server for routing
- provide basic security through Helmet
- send log messages to Fluentd
- send basic metrics about the NodeJS process to Prometheus
- render the site header and footer
The package is very easy to use. Just do an npm install and create a server.js file with the following code:
The createServer function sets up the server. It requires at least a React root element and the chunks output from Webpack. For the data layer, it defaults to GraphQL. The graphql property is an object that contains the type definitions and resolvers for the app.
After initialization, the createServer function returns an object with a start method, which kicks off the Express server which handles the routing on the server.
The server package also exposes tools for logging and metrics. By importing those, a consuming site can add its own logging or send custom metrics to Prometheus.
This is all that is needed to get started. The developers can now focus on building the parts of the site that are really interesting and not worry about the server, or any requirements from our platform (i.e., logging and metrics).
So let’s have a look at what goes on inside the package.
When we call createServer, a new Express server is created. We use
morgan for request logging and skip it for a few specific routes. We then apply some security headers and set up compression. We also create a custom metric to measure the duration of our server side React rendering. Finally, we add the routes. The configuration object is passed, for use in the GraphQL route and the SSR route. For more advanced uses, the object can also contain additional server routes.
There is still a lot of things to do before we can put it into production at scale. For instance, one team has improved the speed by chunking the rendering output, but we haven’t moved that to the server package. Another thing is that we have our header and footer in a separate npm package. Currently, when that package changes, we need to update the server and the micro site, due to a CSS dependency.
But once we have done that, we can apply all those nice features to all micro sites. And if we make any other improvements in the future, we can easily roll them out to all sites.
Thank you for taking the time to reading this story! If you enjoyed reading this story, clap for me by clicking the 👏🏻 below so other people will see this here on Medium.
You can follow me on Twitter @ronderksen and feel free to tweet me anything!
Also, I work at Wehkamp.nl one of the biggest e-commerce companies of 🇳🇱
We do have a Tech blog, check it out and subscribe if you want to read more stories like this one. Or look at our job offers if you are looking for a great job!