Monorepo com Yarn Workspaces + Vue.js + Node.js + Typescript + Github Actions — PARTE 1

Neste aprenderemos como aplicar profissionalmente um projeto full stack monorepo utilizando Yarn Workspaces, Vue.js, Node.js com Typescript e workflow de continuous integration com Github Actions.
Concluiremos em dois episódios com a mão na massa o entendimento para criação do que permeia um projeto desses e um boilerplate pronto para ser utilizado.
TL;DR
O objetivo desse primeiro EP será a explicação do que seria o Yarn Workspaces, pontuações de por que utilizar, configuração do mesmo e das stacks de desenvolvimento (web com Vue.js e server com Node.js e Typescript).
No próximo EP, irei fechar com o workflow de continuous integration utilizando Github Actions.
Antes de mais nada, os requisitos…
- Node.js ≥ v12. Com instalar com nvm aqui
- Yarn. Como instalar aqui
- Vue CLI. Como instalar aqui
Yarn Workspaces?
Resumidamente, essa feature implementada a partir da versão 1.0 do Yarn permite que trabalhemos com vários tipos de pacotes em um único repositório.
Com o Yarn Workspaces temos a possibilidade de deixar mais profissional nosso monorepo javascript 💫.
Por que utilizar?
Além do gerenciamento optimizado dos pacotes em um único repositório, temos também a reutilização de dependências e lock files entre os projetos.
Segue abaixo uma ilustração do funcionamento da reutilização de dependências:
Obs: A comparação com o NPM multi-repo não faz referência alguma com a nova feature de workspaces adicionada a partir do node 15+.

Estruturando o Yarn Workspaces 👨🏽💻
Primeiramente iremos criar uma pasta reservada a implementação e iniciar um projeto novo com a CLI do Yarn. Usando o terminal:
$ mkdir monorepo && cd monorepo
$ yarn init
Após utilizar o comando yarn init, responda o formulário que aparecerá.

A questão do "private: true" está na especificação How To Use It no site oficial do próprio Yarn.
Prosseguindo, temos que adicionar um novo nó no nosso package.json contendo as especificações do nosso monorepo. Pra não termos que ficar informando todos os nomes que daremos para nossas stacks do projeto ou ficar alterando esses nomes sempre que houver alguma modificação, atribuiremos que nossas stacks estarão em uma pasta chamada packages.
Pronto! Configuramos rapidamente nossa estrutura inicial pro ambiente de workspaces.
Configurando o ambiente do Node.js com Typescript
Dentro da nossa pasta packages, criaremos uma pasta chamada server, e novamente executaremos o comando yarn init, porém agora com a flag -y para tornar o processo mais rápido
$ cd packages && mkdir server && cd server
$ yarn init -y
Dentro do projeto iniciado, adicionaremos a dependência express e colaremos um exemplo hello world da própria documentação do express, apenas para conter algo.
Também adicionaremos como dependência de desenvolvimento o pacote de teste jest, que não foi mencionado na introdução dessa página, porém terá seu objetivo no desenvolvimento do EP 2 🤠.
$ yarn add express
$ yarn add typescript jest @types/jest ts-jest -D
Feito isso, utilizaremos o comando para iniciar as configurações do typescript no projeto (lembrando que o foco dessa página não são as configurações em si do mesmo, mas sim a estruturação do boilerplate).
$ yarn tsc --init
Mais uma etapa configurada! Com essas configurações, temos uma estrutura "pelada" inicial pro nosso servidor em node.
Criando nosso ambiente Vue.js
Essa etapa será a mais simples, porém terá um adendo de uma curiosidade prática de uma vantagem de se utilizar Yarn Workspaces para arquiteturas monorepo.
Voltamos a raiz da pasta packages e utilizando o Vue CLI, iniciaremos um projeto Vue.js novo
$ vue create web
Nas opções do terminal, escolha a que melhor atenda a sua necessidade (v2 ou v3) e prossiga.
Para finalizar, adicione o jest como dependência de desenvolvimento ao nossa stack web
$ yarn add jest -D
Acabou. Com essa terceira parte de configuração, estruturamos o boilerplate do nosso projeto inteiro.
Curiosidades
- Se voltarmos na raiz de nosso projeto e usarmos o comando yarn, podemos perceber um comportamento bem peculiar… O Yarn Workspaces ira dedupar dependências em comum, e salvá-las na node_modules da raiz do projeto; Se observarmos a node_modules de nossas stacks, veremos que estão praticamente sem nada, talvez apenas com arquivos ou pastas bin, mostrando na prática a eficiência na tratativa de monorepos!
- Para adição de dependências no módulo global, usamos a flag -W no final do comando; Ex.: yarn add lodash -W.
A flag deixa explícito que desejados adicionar essa dependência a módulo global.
💡 Algo bom a se fazer, é na raiz do projeto criar um arquivo com o nome ".yarnrc" e colar a linha abaixo:
*.ignore-workspace-root-check true
Conclusão
No fim deste temos uma base mais clara e concreta para trabalhar com monorepos utilizando Yarn Workspaces!
Não percam o próximo EP onde irei um pouco mais a fundo estabelecendo workflows de CI para cada stack utilizando Github Actions, fechando os objetivos descritos no início.
Referências
https://planflow.dev/blog/what-is-a-yarn-workspace
https://classic.yarnpkg.com/en/docs/workspaces/
https://expressjs.com/pt-br/starter/hello-world.html