Abílio Azevedo.

Building a Swiss Army Knife: How to Reuse Code with Monorepo Packages

Cover Image for Building a Swiss Army Knife: How to Reuse Code with Monorepo Packages
Abílio Azevedo
Abílio Azevedo

Building a Swiss Army Knife: How to Reuse Code with Packages

In this article, we discuss how to reuse code with private/public packages using a monorepo to scale JavaScript application features.

We explore two solutions: multiple repositories and a single repository (monorepo). We opt for the second option and present some tools, like Turborepo and Changeset, to help manage a monorepo efficiently. Then, we build an architecture with multiple applications and packages. This architecture is ideal for companies with multiple applications and shared components, which seek a scalable approach to software development.

The problem that will be discussed in this article is How to reuse code with private/public packages using monorepo to scale features of your JavaScript Applications.

It is very common for companies to have more than one application, for example:

1 - Application for the client (CLIENT).

2 - Application for system administration (ADMIN).

3 - Several other applications.

With these applications, there will certainly be overlapping code. For example: basic components that can be shared using the famous Design System.

This Design System can be an internal company package, or even public. In addition, these applications can consume similar APIs and we can have an SDK that implements the calls to facilitate their use.

With the scenarios in mind, how can we organize and build our Swiss Army knife?

  • One solution would be to have multiple repositories for each application and package; and upload the packages to NPM Packages or GitHub Packages.
  • This solution can be good when the company has several teams and wants to segregate access to the codes, but it can be very laborious for small teams, when the architecture is not yet very mature, since local development requires the use of symbolic links (yarn link or npm link) to reference the packages and do local development.
  • Another solution is to have a monorepo (single repository) with the applications and packages that can be published on NPM Packages or GitHub Packages (can also be used locally as they are in the same repository).
  • This solution is great for small teams starting their design system and api architecture, aiming for decoupled code and future sharing of public packages.

In this article we will use the second option, but first let's define some concepts and tools:

  • A Monorepo (Monolithic Repository) is a source code management model where all an organization's code is stored in a single repository, rather than being split into several smaller repositories for each project. The goal is to simplify code management and enable easier and more efficient collaboration between teams.
  • Turborepo is a JavaScript library that helps manage monorepos. It provides tools to handle the complexities of working with multiple projects in a single repository, such as dependency management, package versioning, and build management. With Turborepo, you can create, test and publish packages in a monorepo more efficiently and safely.
  • The Changeset library is an extension of the monorepo ecosystem, designed to simplify the way code changes are tracked and managed in a monolithic repository. With Changeset, developers can group changes into sets (called "changesets") and assign those sets to specific packages in a monorepo.

Let's get to work! We will build the following architecture:

monorepo arquitetura

  • App Client: Vite application for the client;
  • App Admin: Vite application for admin;
  • Package Core Api SDK: SDK package for using APIs;
  • Package ESLint Config: Package to share ESLint settings;
  • Package TS Config: Package to share Typescript settings;
  • Package Design System: Package to share UI components.

Step by step:

  1. Fork or copy the base repository.

Repo: https://github.com/kibolho/monorepo-scaffold

Your repo can be public or private. It depends on how you want your project. Remember that certain features on the free account are only available for public repositories like Github Pages. Learn more.

  1. Create a personal access token.

You will need this personal access token to create your packages. So create this key with the following accesses (learn more).

Scope

  1. Add the created key as a secret in the repository.

Save the created key as a secret in the repository to be consumed by the actions in the package deploy flow. Suggested name: GH_REGISTRY_PACKAGES. This name will be used in the deploy workflow. Learn more.

  1. Add permissions in your repository for the workflow.

Your package deploy workflow will need to read and write to the repository in addition to creating pull requests to approve new versions. Learn more. Permissions

  1. Add permissions in your repository for GitHub Pages.

As we need to build our assets before deploying, we will use Github Actions. For this it is necessary to give the workflow permission to upload the assets to GitHub Pages. Learn more.

5) Adicione permissões no seu repositório para o GitHub Pages.

  1. Clone your repository to your machine.

Run the following command (learn more):

git clone git@github.com:kibolho/monorepo-scaffold.git
  1. Increment the version of your package.

Run the following command

yarn changeset

changeset

  1. Deploy.

Now just commit and the workflows will be triggered. workflow

  1. Approve the pull request created by Changeset. aprove changeset

  2. Package created and ready to use.

Now we have the package created and it can be downloaded using the GitHub registry.

monorepo scalfold

monoreposcalfold

  1. Using the package.

The default registry is NPM, so to download the package from GitHub you need to point to the GitHub registry.

And if you want to use the packages privately: Create or edit the ~/.npmrc file and replace PERSONAL-ACCESS-TOKEN with your token created in step 2. The ~/.npmrc file is responsible for NPM's global settings.

//npm.pkg.github.com/:_authToken=PERSONAL-ACCESS-TOKEN

As you could see, the focus was more on architecture, I didn't go too deep into the code because there are many technologies involved, maybe in future articles I'll go deeper! Some observations:

  • The Client application in the code was left with just the Vite Hello World, since the concept was shown in the Admin application;
  • I created a workflow that deploys the Client and Admin application to different S3 buckets since GitHub pages does not support multiple applications per repository, let's follow this feature suggestion here.

As the repository is public feel free to propose improvements 😀 like:

  • Deploy on Vercel;
  • Evolve the design-system and api-core-sdk packages with public APIs;
  • Create a real application on top of the architecture.

Final Admin Application - https://kibolho.github.io/monorepo-scaffold/ Aplicação Admin Final

Until next time! That is All Folksundefined


More posts

Cover Image for Upload to AWS S3 using Django, Boto3 and S3Direct

Upload to AWS S3 using Django, Boto3 and S3Direct

Uploading videos via a React Native mobile app to a bucket on the AWS S3 service using S3 Direct and Boto3 with a pre-signed URL.

Abílio Azevedo
Abílio Azevedo
Cover Image for Factory Health Monitor

Factory Health Monitor

The application is a tool for evaluating the health of various machines in an automobile manufacturing plant. This plant features a range of machines, each with specific data points that you will use to assess the condition of the production process.

Abílio Azevedo
Abílio Azevedo

NewsLetter

I will send the content posted here. No Spam =)

Experienced Software Engineer with degree in Electrical Engineering with over 8 years of hands-on expertise in building robust and scalable mobile, web and backend applications across various projects mainly in the fintech sector. Mobile (React Native), Web (React and Next.JS) and Backend (Node.JS, PHP and DJANGO). My goal is to create products that add value to people. - © 2024, Abílio Azevedo