With an increasing amount of services being created on our backend, our frontend development started to be impacted by how many repos and servers you needed to install locally to get the frontend going. And if we also take into consideration our frontend architecture rework, we knew we had to take action in order to have a fast and smooth development experience. That is where our monorepo mock server comes in.
A little bit about LumApps
If you do not know about LumApps, we are a global tech company with R&D teams in France that provides our customers a SaaS Digital Workplace solution, which creates a holistic workspace, integrated with several suites and collaboration tools. Want to know a little bit more about us? Head over to LumApps.com and take a look!
What we needed
Up until a couple of years ago, our frontend application was pretty straightforward to launch in your own development environment to start coding. You executed the frontend and the backend, and that was it! But since the company and the application have grown exponentially over the last couple of years, with new services created and new developers coming in to develop the product, booting the application locally was not that easy as it used to be.
These new services meant that you would need to configure them in your machine, which not only took time to setup, but also a lot of CPU, thus creating a really tough combination for our development environments. We needed a system that allowed us to:
- Remove those services dependencies for local development and have a single server that served the data that the frontend needed for local development, and thus, increasing local development time 🚀
- Create a set of data that all teams could reuse in order to develop their functionalities. This meant sharing that data across teams and allowing those teams to create their own data sets in order to remove/add configuration for each specific team configuration 🛠
- Have a consistent set of data that can be reused for unit and integration tests ✅
How we did it
After some research, we found a nifty npm module called json-server that allowed us to create a full fake REST API with really no configuration at all. It is really an amazing tool, since it not only allow to mock data and create a server, but it provides a lot of core API functionalities out of the box, which makes this tool really the next level when it comes to mocking. With it, we could for example execute a POST to create a resource and the next time we do a GET for retrieving the list of resources, the recently created resource would be there! It also allows usto create express js middlewares that can be used to tweak requests and response, giving us full access to change whatever we want!
On top of that, we created a small node js file that allowed us to easily manage these mock files on a monorepo. Basically json-server needs an json entrypoint where the mock data lives, but since we are using a monorepo architecture, we wanted to each package to have their own mock data so they are the owners of that data and furthermore, it allows us to clearly see the endpoints that a package consumes. This node js file is a script executed before json-server and it:
- Goes through each of the packages in our workspace and searches for files named api.json on the _mocks folder and combines all of them into a single file with all the data from each package. It also takes into consideration the other json-server configurations, such as routes or middlewares, and puts them all together in a single location
- Writes into a predefined folder those combined files and executes json-server with those files as input.
- This is all executed in a single command yarn mocks which creates the files and then launches json-server.
- We also allowed each module to create different scenarios for their API responses, which we call overrides. Each package can create as many overrides as they want, which are a subset of the data that the API returns, with different values overriden and changed so that the API returns a different scenario. So for example, our API response for our notifications service looks like this:
But what if we wanted to easily launch a frontend where the user does not have any notifications at all? In that case we create the override no-notifications.api.json that overrides this file:
At a folder level, our notifications package looks like this:
And in order to apply those overrides, we just launch yarn mocks -override no-notifications and our node js file will look for the different overrides created on each package with the name no-notifications and merge deep their values with the original values of the each API response. This also meant that if there are other packages that want to create an override for the no-notifications scenario they can also do that! They just need to create a file called no-notifications.api.json in their _mocks folder.
Finally, you can also apply several overrides at once by doing yarn mocks -override no-notifications,admin,no-posts. This will apply those overrides one after the other, overriding each key in the API responses in the provided order.
What is next
We still need to go through a couple more scenarios that we want to tackle to allow our developers to have a more fluid development experience:
- Automatically create mocks from a remote backend service.
- Periodically validate these mocks against a remote backend service in order to check that the API response did not change.
- Open source this small node js script so those of you out there that are using monorepos and want to reuse this code can do it! Stay tuned for future developments on this subject!