Use of the mono-repository to accelerate the development process
The HOQU’s platform development is a complex project. We are presented with the task of developing three apps for three different kinds of users. And there is a code that can be reused between the apps. For speeding up development, it is important that the applications be assembled from existing parts of the code in a simple and understandable way.
Using a mono-repository (monolithic repository) differs from using several repositories by the fact that the entire code is located in the same repository.
The repository is monolithic when the following conditions are met:
1) The repository contains more than one logical project;
2) These projects may be unrelated, partially related, or related by other means (for example, through a dependency management system).
3) The repository is considered large in many ways:
- By the number of commits;
- By the number of branches and / or tags;
- By the number of files;
- By the size of the content (i.e. folder size).
One of our most reused components is the Button, and as part of our UI, it should be easily shared between projects.
One of the more complex components is the Menu component, which is widely used in all 3 of our apps.
A profile page for affiliates and merchants fully shares both presentation and logic between the two apps.
Obviously, the UI is reused between our apps, but more importantly, as you can see, we need to fully reuse all of the logic and presentation of some of the pages while maintaining flexibility and speed of development.
This is a most common approach when it comes to developing apps with the same core package, but it came with the following disadvantages:
- Versioning apps can become a total mess and eventually it can become difficult to keep the core package consistent for all of the apps due to bug fixes and slight differences for different kinds of users.
- Developing in 4 different repos can become cumbersome and slow due to the need of switching repos and running the tests manually when one changes the core package. Git submodules are a partial solution, but community consensus on this is “just don’t” even though in the brief time that we tried using them we didn’t encounter any difficulties.
The more complex answer to reusing most of our code was using Lerna + yarn workspaces. By using the experience of giants like Google, Facebook and Twitter, we decided to try the monorepo approach.
Trying Lerna (Lerna — a tool that optimizes the workflow around managing multi-package repositories with git and npm) was a simple choice for us, as it was used by great open-source projects, such as Babel and React for managing npm packages in a mono-repository. We tested adopting a monorepo approach when we were close to finishing our second app. We set our goals on trying to extract a core package which contained everything, and making two apps fully modular with importing reusable parts of our apps from a core package while keeping all of the unique components and major differences in the app’s package.
While moving to a monorepo structure did not present too big of a challenge, nevertheless, it took some time to separate a core package (for example, lots of manual renaming of imports and manual testing). The good sides were apparent immediately, as we mitigated both of the disadvantages I mentioned above while adding the following benefits:
- Easy bootstrap for new developers — just type lerna bootstrapand the dependencies will interlink without the need of running yarn install for all of the projects. Additionally, using yarn workspaces will save space as it uses a single node_modules folder when bootstrapping the projects.
- A single place for all of our configs, which includes linting, testing, building and deploying all of our apps — our root folder. All of the commands are contained in the package.json and lerna allows to run all of the scripts in parallel and that in turn saves time when developing and deploying.
Configuring the CI (Continuous Integration) of our projects was also not a difficult task, because we use Gitlab CI and all of our projects’ deploy is automated. However, in the future, as our project grows, we consider moving to more advanced continues options such as Travis CI.
As a conclusion, for us using a monolithic source control doesn’t mean that we have a monstrous inseparable codebase. On the contrary, it empowers us to make our code more modular and easier to share between different projects.
Until next time!
The HOQU team