Alura > Cursos de Front-end > Cursos de React > Conteúdos de React > Primeiras aulas do curso React: aplicando arquiteturas de Micro frontends

React: aplicando arquiteturas de Micro frontends

Entendendo micro-frontends - Apresentação

Apresentando o curso e o instrutor

Olá, estudante da Alura! Meu nome é Pedro, sou instrutor de front-end na Alura.

Audiodescrição: Pedro é um homem branco, com cabelo e barba escuros. Ele veste roupas pretas e está em um ambiente iluminado pelas cores rosa e azul.

Seja bem-vindo a mais um curso de React na nossa plataforma da Alura. Este curso pode agregar muito valor, pois abordaremos um problema significativo em projetos monolíticos e como resolvê-lo utilizando a arquitetura de micro front-end.

Introduzindo o conceito de micro front-end

Vocês solicitaram bastante conteúdo sobre micro front-end, e estamos aqui para trazer o que há de mais novo e moderno nessa solução para projetos front-end.

Se você já se deparou com projetos monolíticos, difíceis de implementar, se o seu deploy demora muito tempo, ou se deseja aprender uma nova habilidade e avançar na sua carreira, este curso é para você. Ele oferece a oportunidade de trabalhar com diferentes arquiteturas no universo front-end.

Explorando o projeto do curso

Atualmente, temos o projeto do Lay, que estou exibindo no meu navegador. Trata-se de um projeto com uma lista de livros que podemos salvar para consulta posterior. Vamos implementar um micro front-end a partir da tela de login.

O que é um micro front-end? Como faremos essa renderização? Como isso ocorrerá? Como está o projeto? Vamos com calma, pois neste projeto começaremos com um monorepositório. Teremos uma introdução breve sobre o que é um monorepositório, já que, neste nível do curso, espera-se que tenhamos um conhecimento prévio sobre o funcionamento básico de projetos em React e suas configurações. Não apenas entender como o React funciona, mas também como configurar um projeto do zero. Passaremos rapidamente por essa parte, relembrando alguns pontos, mas o foco será trabalhar com micro front-ends.

Detalhando as tecnologias e ferramentas utilizadas

Abordaremos a utilização de TypeScript, estilização com Tailwind, gerenciamento de estados globais nas aplicações com Redux, e as configurações básicas de Webpack. Utilizaremos o TurboRepo, mas não é necessário ter experiência prévia com ele, pois forneceremos informações ao longo do curso. Além disso, é importante já termos conhecimento das configurações básicas de NPM, utilizando YARN, NPM ou PNPM. Essas habilidades são essenciais antes de entrarmos no mundo dos micro front-ends.

Convidando para a jornada de aprendizado

Exploraremos muitos aspectos interessantes no projeto, como renderizações condicionais e tree shaking (eliminação de código morto). Convidamos todos a mergulhar nesse universo dos micro front-ends, pois acreditamos que este conteúdo será muito enriquecedor. A arquitetura de micro front-end é uma abordagem muito interessante para utilizarmos. Na sequência, começaremos com o passo inicial para entender o problema dos monolitos e como resolvê-lo com micro front-ends. Aguardamos todos nessa jornada!

Entendendo micro-frontends - Aprendendo sobre monolitos e microfrontends

Discutindo problemas de arquitetura em monolitos

Vamos discutir sobre a arquitetura para projetos front-end, especificamente a utilização de micro front-ends. Os micro front-ends surgem como solução para problemas de arquitetura frequentemente encontrados em monolitos. Antes de abordarmos os micro front-ends em si, é importante entender o problema que tentamos resolver nos monolitos.

Em um cenário de monolito, consideremos uma empresa grande com muitos desenvolvedores, onde há uma única base de código, ou seja, um único repositório para todo o produto. Nesse repositório, todas as funcionalidades estão misturadas. Quando precisamos fazer o deploy de uma pequena alteração, como mudar o texto de um botão em uma parte logada do aplicativo, isso pode se tornar um problema. Por exemplo, em um e-commerce, o que esse botão na parte logada tem a ver com o restante da aplicação, como o carrinho ou a listagem de itens? Um deploy pequeno pode se transformar em uma grande dor de cabeça, pois precisamos fazer o deploy de tudo, mesmo que seja uma alteração mínima. Isso pode bloquear toda a equipe devido a esses deploys. Se houver um bug em produção, toda a empresa pode ficar parada até que o problema seja resolvido e o ambiente de produção atualizado.

Outro problema comum em projetos com arquitetura de monolito é a dependência de versões de tecnologia. Por exemplo, se quisermos migrar do React 16 para o React 18, isso pode ser muito trabalhoso. Não é impossível, mas a tendência é que muitas coisas quebrem, exigindo refatorações desnecessárias devido a uma simples atualização de bibliotecas. A complexidade do monolito é exponencial, o que significa que a quantidade de problemas pode ser muito grande e, com o tempo, cada mudança na aplicação pode se tornar demorada e custosa, não apenas financeiramente, mas também em termos de esforço.

Considerando a adoção de micro front-ends

Uma regra básica ao considerar o uso de micro front-ends é que, se não estamos enfrentando problemas ou dores de um monolito, não precisamos utilizá-los. Se não nos identificamos com esses problemas, talvez os micro front-ends não sejam a solução recomendada. No entanto, é importante entender quando e por que utilizá-los, e é para isso que este curso existe, para explorar as possibilidades de resolução de problemas.

Os problemas com monolitos são comuns, mas precisamos nos atentar a alguns pontos. Separei três pontos essenciais:

  1. Se temos mais de oito ou dez pessoas desenvolvedoras front-end trabalhando em um único repositório, a chance de problemas e gargalos durante o deploy é grande. Times muito pequenos ou muito grandes são difíceis de manter, e é importante que a liderança tenha bom senso ao montar as equipes.

  2. Se o deploy está demorando mais de trinta minutos, há algo errado. Isso indica que muita coisa está sendo deployada ao mesmo tempo, e cabe investigar se podemos aplicar melhorias na arquitetura com micro front-ends. Um deploy razoável deve levar de dois a cinco minutos.

  3. Em um contexto de e-commerce, por exemplo, com muitas funcionalidades e ciclos de vida diferentes, pode ser interessante adotar uma arquitetura de micro front-end. Isso se aplica a funcionalidades como login, autenticação de usuário, listagem de itens, carrinho, checkout e gerenciamento de pagamentos internos.

Esses pontos são sinais de que pode haver uma oportunidade de melhorar a arquitetura do projeto com micro front-ends.

Avaliando quando utilizar micro front-ends

Quando devemos ou não utilizar micro front-ends? Em projetos pequenos ou médios, com poucas pessoas desenvolvedoras, a complexidade pode aumentar desnecessariamente. Em casos de MVPs (Produto Mínimo Viável) ou protótipos, que exigem velocidade inicial de desenvolvimento, a arquitetura de micro front-ends não é ideal, pois adiciona complexidade. Muitas vezes, MVPs e protótipos acabam se tornando o produto final, embora essa não seja a intenção. No mundo ideal, não usaríamos MVPs e protótipos como produtos finais. No entanto, na prática, frequentemente somos pressionados a transformar um MVP ou protótipo em um produto final pronto para produção. Isso exige uma implementação rápida e mudanças na arquitetura. Se o projeto tem potencial para se tornar um produto final, a utilização de micro front-ends pode ser considerada. Fora isso, não é recomendado usar essa arquitetura em MVPs e protótipos.

Se o time é coeso e trabalha bem junto, não há necessidade de utilizar micro front-ends. Quando a complexidade adicional não é justificada pelo tamanho do projeto, é importante ponderar se realmente vale a pena mudar a arquitetura.

Explorando a modularidade dos micro front-ends

Micro front-ends podem ser comparados a blocos de LEGO, onde cada bloco funciona de forma independente. Por exemplo, o módulo de login pode ser removido de uma aplicação e integrado a outra, pois o front-end está dividido em partes menores e independentes. Cada parte tem seu próprio deploy e ciclo de vida, e cada time é responsável por seu pedaço do front-end. Isso permite que cada time escolha sua stack de tecnologia, como React, Vue ou Angular, dentro do escopo JavaScript.

Um exemplo prático é um e-commerce, onde o container principal, ou shell, recebe todos os micro front-ends. Cada loja dentro do shopping representa um time, com regras em comum, como horários de funcionamento. O shell coordena as informações antes de qualquer aplicação no front-end separado. Regras comuns incluem design systems e padrões compartilhados de componentes e estado global.

Benefícios e implementação dos micro front-ends

Os micro front-ends permitem deploy independente, o que agiliza atualizações. Os times se tornam mais autônomos, com liberdade para definir regras e organização de deploys e testes. A escalabilidade é excelente, pois mudanças podem ser feitas sem conflitos com outros projetos. A migração gradual é possível, permitindo trocar tecnologias sem interferir nos demais projetos.

Para utilizar micro front-ends, começamos com um monolito front-end, identificamos domínios de negócio, como checkout, carrinho, produtos e login, e criamos micro front-ends a partir desses domínios. Criamos um projeto central, o shell, que recebe os micro front-ends e define os deploys. Isso garante isolamento de falhas, aumentando a resiliência da aplicação e permitindo correções rápidas e localizadas.

Na sequência, discutiremos a comunicação entre micro front-ends, separados por tecnologia e domínio.

Entendendo micro-frontends - Lidando com a comunicação entre microfrontends

Discutindo a comunicação entre micro front-ends

Vamos discutir a comunicação entre micro front-ends e como podemos solucionar esse desafio. Os micro front-ends são independentes, mas precisam interagir e compartilhar informações. Por exemplo, como o sistema de login pode informar ao cabeçalho da aplicação que o usuário está logado, independentemente de estar no shell, que é nosso container principal, ou em outro micro front-end? Como avisamos ao cabeçalho que as informações foram alteradas e recebemos esse feedback do back-end?

A primeira abordagem, que é a mais comum em JavaScript, é através de listeners, ou seja, utilizando os custom events nativos do navegador. Essa opção é vantajosa por ser simples, nativa e não depender de bibliotecas externas. Não precisamos nos preocupar com o funcionamento do navegador, pois ele já suporta essa funcionalidade em todos os navegadores. Assim, não há necessidade de interferências externas.

Ilustrando o uso de custom events

Para ilustrar essa abordagem, podemos ver como o MFE de Login dispara um evento customizado quando um usuário faz login:

// MFE Login dispara
window.dispatchEvent(new CustomEvent('user:login', {
  detail: { userId: '123', name: 'João' }
}));

E como o MFE de Header pode escutar esse evento para atualizar o estado do usuário:

// MFE Header escuta
window.addEventListener('user:login', (e) => {
  setUser(e.detail);
});

No entanto, há um problema: ao utilizar disparos de eventos customizados, se não tivermos uma tipagem adequada, pode-se tornar confuso e problemático lidar com tipagens incorretas nesses disparos de eventos. Apesar disso, é uma forma simples e rápida de implementação. Inclusive, utilizaremos alguns custom events em nosso projeto, que será aprimorado dentro do layer, o projeto que trabalharemos neste curso. Contudo, não nos limitaremos apenas aos custom events.

Utilizando estado compartilhado com Store Global

Também utilizaremos estado compartilhado, através de um Store Global. Podemos usar o Redux, o Zustand, ou outras bibliotecas que fazem o gerenciamento de estado global da aplicação. Essas opções são tipadas e mais organizadas, pois operam dentro de um framework ou biblioteca com regras definidas.

Aqui está um exemplo de como podemos definir uma Store compartilhada usando Zustand:

// Store compartilhada (ex: Zustand, Redux)
const useGlobalStore = create((set) => ({
  user: null,
  setUser: (user) => set({ user }),
}));

Entretanto, surge um pequeno acoplamento, pois todos os projetos que utilizarem esse Store Global precisarão compartilhar a dependência. Se, por exemplo, um projeto que necessita dessas informações globais não funcionar com Zustand ou Redux, pode ser que o compartilhamento global não funcione, exigindo outras formas de comunicação.

Considerando a utilização de props via Shell

Se sabemos que a stack é segura e todos estão trabalhando com JavaScript, React ou suas variações, podemos utilizar Zustand, Redux ou Recoil, que são opções familiares para quem trabalha com JavaScript e React. Contudo, é importante prestar atenção ao escolher a biblioteca com a qual trabalharemos.

Por fim, temos um exemplo básico de uma Store compartilhada usando UseGlobalStore, que precisamos criar para todos os projetos terem acesso.

Não é algo extremamente complicado, na verdade, é até mais fácil de implementar do que os próprios Custom Events (eventos personalizados). No entanto, é importante lembrar que a questão do acoplamento é muito crítica. Nós utilizamos os Microfront Ends para reduzir o acoplamento, mas ao usar o estado compartilhado, ou Store Global, acabamos criando um acoplamento no gerenciamento de estado.

Explorando a passagem de props via Shell

A terceira opção, que não é ruim, mas é arriscada, é a utilização de props via Shell. Isso significa que passamos props dentro da nossa tag de componente, enviando um objeto grande para dentro dos Microfront Ends através do Shell. Dessa forma, conseguimos trabalhar facilmente com essas props dentro dos Microfront Ends. Essa abordagem é explícita e fácil de entender, pois definimos essas props e objetos em um único local, que é o nosso Shell. No entanto, o Shell pode se tornar um gargalo.

Veja como o Shell pode passar props para os Microfront Ends:

// Shell passa props para MFEs
<LoginMFE onLogin={(user) => setGlobalUser(user)} />
<HeaderMFE user={globalUser} />

Cada uma dessas opções tem pontos positivos, mas é essencial pensar cuidadosamente sobre qual utilizar e por que utilizá-la, para evitar problemas, especialmente quando trabalhamos com o Store Global e com as props via Shell, pois podem gerar um nível de acoplamento dependendo das informações que transitamos.

Recomendando abordagens para o projeto

Um exemplo básico de código seria ter um Shell, que é nossa aplicação global, e dentro dela dois Microfront Ends, como o Login MFE e o Header MFE. O Login MFE poderia receber uma função para obter os dados do usuário, enquanto o Header MFE receberia os dados do usuário global para definir as informações no Header.

Nossa recomendação é começar com Custom Events para as funcionalidades mais simples, já que não lidaremos com complexidades neste projeto. Assim, podemos trabalhar apenas com Custom Events, como na parte de Login. Este não será um Login sofisticado, pois temos um curso específico de autenticação. Será um Login apenas para exemplificar e ultrapassar a barreira de rota protegida, além de uma parte de Favoritos, que salvaremos no armazenamento do Local Storage ou Session Storage, conforme a preferência durante o desenvolvimento.

Se trabalharmos com algo mais complexo, poderíamos evoluir para uma Store compartilhada. No entanto, como o objetivo não é aprender sobre Redux ou Zustand, mas sim sobre Microfront Ends e comunicação, trabalharemos apenas com Custom Events. Podemos, no máximo, utilizar o gerenciamento do próprio React, como o Context. Utilizaremos a API de Contexto para as informações, já que estaremos usando apenas o React, e podemos usar o Context para identificar essas informações dentro dos nossos projetos.

Na sequência, discutiremos mais sobre as abordagens que utilizaremos neste curso e por que precisamos explorar todas as três antes de finalizar o projeto. Nos encontraremos em breve para continuar essa discussão.

Sobre o curso React: aplicando arquiteturas de Micro frontends

O curso React: aplicando arquiteturas de Micro frontends possui 262 minutos de vídeos, em um total de 40 atividades. Gostou? Conheça nossos outros cursos de React em Front-end, ou leia nossos artigos de Front-end.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda React acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas