Construindo um canivete suíço: Como reutilizar código com pacotes

Construindo um canivete suíço: Como reutilizar código com pacotes

Neste artigo, discutimos como reutilizar código com pacotes privados/públicos utilizando um monorepo para escalar funcionalidades de aplicações JavaScript.

Exploramos duas soluções: múltiplos repositórios e um único repositório (monorepo). Optamos pela segunda opção e apresentamos algumas ferramentas, como o Turborepo e o Changeset, para ajudar a gerenciar um monorepo eficientemente. Em seguida, construímos uma arquitetura com várias aplicações e pacotes. Essa arquitetura é ideal para empresas com múltiplas aplicações e componentes compartilhados, que buscam uma abordagem escalável para o desenvolvimento de software.

O problema que será discutido neste artigo é Como reutilizar código com pacotes privados/públicos utilizando monorepo para escalar funcionalidades de suas Aplicações JavaScript.

É muito comum empresas terem mais de uma aplicação, por exemplo:

1 - Aplicação para o cliente (CLIENT).

2 - Aplicação para administração do sistema (ADMIN).

3 - Diversas outras aplicações.

Com essas aplicações, com certeza haverá uma sobreposição de código. Como por exemplo: componentes básicos que podem ser compartilhados usando o famoso Design System.

Esse Design System pode ser um pacote interno da empresa, ou até mesmo, público. Além disso, essas aplicações podem consumir APIs semelhantes e podemos ter um SDK que implementa as chamadas para facilitar o uso das mesmas.

Com os cenários em mente, como podemos organizar e construir nosso canivete suíço?

  • Uma solução seria ter múltiplos repositórios para cada aplicação e pacote; e subir os pacotes no NPM Packages ou GitHub Packages.
  • Essa solução pode ser boa quanto a empresa tem diversos times e se quer segregar o acesso aos códigos, porém pode ser muito trabalhosa para times pequenos, quando a arquitetura ainda não está muito madura, já que o desenvolvimento local exige o uso de links simbólicos (yarn link ou npm link) para referenciar os pacotes e fazer o desenvolvimento local.
  • Outra solução é ter um monorepo (único repositório) com as aplicações e os pacotes que podem ser publicados no NPM Packages ou GitHub Packages (também podem ser usados localmente por estarem no mesmo repositório).
  • Essa solução é muito boa para times pequenos que estão iniciando sua arquitetura de design system e apis, visando um código desacoplado e futuro compartilhamento de pacotes públicos.

Nesse artigo vamos utilizar a segunda opção, mas antes vamos definir alguns conceitos e ferramentas:

  • Um Monorepo (Monolithic Repository ou repositório monolítico) é um modelo de gerenciamento de código-fonte em que todo o código de uma organização é armazenado em um único repositório, em vez de ser dividido em vários repositórios menores para cada projeto. O objetivo é simplificar o gerenciamento do código e permitir uma colaboração mais fácil e eficiente entre equipes.
  • O Turborepo é uma biblioteca JavaScript que ajuda a gerenciar monorepos. Ele fornece ferramentas para lidar com as complexidades de trabalhar com múltiplos projetos em um único repositório, como gerenciamento de dependências, versionamento de pacotes e gerenciamento de build. Com o Turborepo, é possível criar, testar e publicar pacotes em um monorepo de forma mais eficiente e segura.
  • A biblioteca Changeset é uma extensão do ecossistema de monorepo, projetada para simplificar a maneira como as alterações de código são rastreadas e gerenciadas em um repositório monolítico. Com o Changeset, os desenvolvedores podem agrupar as alterações em conjuntos (chamados de "changesets") e atribuir esses conjuntos a pacotes específicos em um monorepo.

Mãos à obra! Vamos construir a seguinte arquitetura:

  • App Client: Aplicação Vite para o cliente;
  • App Admin: Aplicação Vite para o admin;
  • Package Core Api SDK: Pacote SDK para utilização das apis;
  • Package ESLint Config: Pacote para compartilhar as configurações de eslint;
  • Package TS Config: Pacote para compartilhar as configurações de typescript;
  • Package Design System: Pacote para compartilhar componentes UI.

Passo a passo:

1) Faça um fork ou copie o repositório base.

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

O seu repo pode ser público ou privado. Depende de como você vai querer seu projeto. Lembrando que certos recursos na conta gratis só estão disponíveis para repositórios públicos como o Github Pages. Saiba mais.

2) Crie uma chave de acesso pessoal.

Você vai precisar dessa chave de acesso pessoal para poder criar seus pacotes. Por isso crie essa chave com os seguintes acessos (saiba mais).

3) Adicione a chave criar como um segredo no repositório.

Salve a chave criada como segredo no repositório para ser consumida pelas actions no fluxo de deploy dos pacotes. Sugestão de nome: GH_REGISTRY_PACKAGES. Esse nome será usado no workflow de deploy. Saiba mais.

4) Adicione permissões no seu repositório para o workflow.

Seu workflow de deploy dos pacotes vai precisar ler e escrever no repositório além de criar pull request para aprovar novas versões. Saiba mais.

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

Como precisamos buildar nossos assets antes de fazer o deploy, vamos usar o Github Actions. Para isso é necessário dar permissão para o workflow fazer o upload dos assets para o GitHub Pages. Saiba mais.


6) Clone seu repositório para sua máquina.

Rode o seguinte comando (saiba mais):

git clone git@github.com:kibolho/monorepo-scaffold.git

7) Incremente a versão do seu pacote.

Rode o seguinte comando

yarn changeset


8) Deploy.

Agora é só commitar e os workflows serão acionados.

9) Aprovar o pull request criado pelo Changeset.

10) Pacote criado e pronto para ser usado.

Agora temos o pacote criado e pode ser baixado usando o registry do GitHub.

11) Usando o pacote.

O registry padrão é o NPM, então para baixar o pacote do GitHub é preciso apontar para o registry do GitHub.

E caso você queira usar os pacotes de forma privada: Crie ou edite o arquivo ~/.npmrc e substitua PERSONAL-ACCESS-TOKEN pelo seu token criado no passo 2. O arquivo ~/.npmrc é responsável pelas configurações globais do NPM.

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

Como vocês puderam ver, o foco foi mais na arquitetura, não aprofundei tanto no código porque são muitas tecnologias envolvidas, quem sabe em próximos artigos eu aprofundo mais! Algumas observações:

  • A aplicação Client no código ficou somente com o Hello World do Vite, já que o conceito foi mostrado na aplicação Admin;
  • Criei um workflow que faz o deploy pro S3 da aplicação Client e Admin em buckets diferentes já que o GitHub pages não suporta multiplos aplicações por repositório, vamos acompanhar essa sugestão de feature aqui.

Como o repositório é público fique a vontade para propor melhorias 😀 como:

  • Fazer o deploy na Vercel;
  • Evoluir os pacotes design-system e api-core-sdk com apis públicas;
  • Criar uma aplicação real em cima da arquitetura.

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

Até a próxima!

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.