Você está enfrentando desafios ao escalar seu front-end para atender a um número crescente de usuários? Com o aumento da complexidade das aplicações web modernas, estratégias como micro front-ends, monorepositórios, gerenciamento de estados globais e otimização de cache são essenciais. 

Neste artigo, exploramos as melhores práticas para escalar aplicações front-end, discutindo como implementar micro front-ends, gerenciar versões em monorepositórios, aplicar estratégias eficazes de cache e manter estados globais de forma eficiente. 

Descubra como o Nubank está superando os desafios de escalabilidade no front-end e como você pode aplicar essas abordagens para construir interfaces de usuário ágeis, responsivas e fáceis de manter.

O desafio da escala

Empresas como o Nubank enfrentam desafios únicos. Com mais de 100 milhões de clientes no Brasil, México e Colômbia, lidar com sistemas distribuídos de larga escala não é apenas uma necessidade, mas uma obrigação. A complexidade de gerenciar transações como o PIX, garantir a estabilidade dos serviços e proporcionar uma experiência consistente ao usuário requer soluções inovadoras.

Além disso, trabalhar com tecnologias avançadas como Clojure e Datomic—cujo desenvolvimento é influenciado por engenheiros dentro do próprio Nubank—adiciona camadas adicionais de complexidade e oportunidade. Essas tecnologias não são apenas ferramentas; são parte integral da estratégia de escalabilidade e inovação contínua.

Conheça nossas oportunidades

Micro front-ends: dividindo para conquistar

A arquitetura de micro front-ends emergiu como uma solução para muitos dos desafios enfrentados por grandes equipes de desenvolvimento. Mas o que exatamente são micro front-ends?

O que são (e o que não são) micro front-ends

Micro front-ends são uma extensão do conceito de microserviços para o front-end. Eles permitem que diferentes equipes desenvolvam, implementem e mantenham partes distintas da interface do usuário de forma independente. 

Isso significa que cada equipe pode trabalhar em seu próprio ritmo, escolher suas próprias tecnologias (até certo ponto) e implantar atualizações sem impactar o sistema como um todo.

É importante destacar que micro front-ends não são:

  • Pacotes NPM ou módulos monolíticos: simplesmente dividir um monolito em pacotes não oferece os benefícios de implantação independente ou isolamento de equipes.
  • Aplicativos separados para o usuário final: a experiência do usuário deve ser unificada. Não estamos falando de vários aplicativos distintos, mas de uma única aplicação composta por várias partes autônomas.

Benefícios dos micro front-ends

  • Implantações independentes: equipes podem implementar atualizações sem coordenar com toda a organização.
  • Escalabilidade de equipes: novos desenvolvedores podem ser incorporados mais rapidamente, focando em uma parte específica do sistema.
  • Isolamento de falhas: problemas em um micro front-end não necessariamente afetam todo o aplicativo.
  • Flexibilidade tecnológica: possibilidade de utilizar diferentes frameworks ou bibliotecas, embora isso deva ser feito com cautela para evitar sobrecarga no cliente.

Custos e considerações

  • Setup inicial complexo: implementar micro front-ends exige um planejamento cuidadoso e uma configuração inicial robusta.
  • Coesão da experiência do usuário: garantir que a interface seja consistente e coesa é um desafio quando múltiplas equipes estão envolvidas.
  • Sobrecarga de performance: o uso de diferentes frameworks pode aumentar o tamanho do bundle e afetar o desempenho.
  • Observabilidade e depuração: monitorar e depurar uma aplicação composta por múltiplos micro front-ends requer ferramentas e práticas avançadas.

Estratégias de implementação

Existem várias abordagens para implementar micro front-ends:

Composição no lado do cliente

É a abordagem mais comum, onde a integração dos micro front-ends ocorre no navegador do usuário. Tecnologias como Web Components, Module Federation (Webpack 5) e frameworks como Single SPA facilitam essa composição.

Composição no servidor ou CDN

A montagem dos micro front-ends ocorre antes de chegar ao cliente, seja no servidor ou na CDN. Ferramentas e técnicas como Edge Side Includes (ESI) podem ser utilizadas.

Comunicação entre micro front-ends

A comunicação eficiente é essencial. Recomenda-se o uso de:

  • Eventos customizados: permitem que micro front-ends se comuniquem sem depender diretamente um do outro.
  • Estados compartilhados via APIs do navegador: como Local Storage ou IndexedDB.
  • Evitar dependências globais excessivas: minimiza o acoplamento entre os componentes.

Controle de versão em monorepositórios

Gerenciar versões em um monorepositório pode ser um desafio, especialmente quando múltiplas equipes estão trabalhando em diferentes partes do sistema. Aqui estão algumas práticas para lidar com isso:

Versionamento individual de pacotes

Ferramentas como Lerna ou Nx permitem que você gerencie versões individuais de pacotes dentro de um monorepositório. Isso possibilita que cada equipe controle as versões de seus próprios componentes ou módulos, mantendo a independência e facilitando a coordenação.

Evitando submódulos git

Embora submódulos Git possam parecer uma solução, eles geralmente introduzem complexidade adicional. Em vez disso, utilizar workspaces do NPM ou Yarn pode simplificar o gerenciamento de dependências internas.

Benefícios do monorepositório

  • Consistência de código: Facilita a padronização e reutilização de código.
  • Visibilidade: todas as equipes têm acesso ao código-fonte completo, promovendo colaboração.
  • Automação: facilita a configuração de pipelines de CI/CD que abrangem todo o sistema.

Estratégias de cache para carregamento de bundles

A eficiência no carregamento de recursos é crucial para o desempenho da aplicação. Estratégias de cache bem implementadas podem melhorar significativamente a experiência do usuário.

Cache de recursos compartilhados

Ao usar tecnologias como Module Federation, é possível compartilhar dependências comuns entre diferentes micro front-ends, evitando downloads redundantes. Para isso:

  • Defina módulos compartilhados: configure quais bibliotecas ou frameworks devem ser compartilhados para evitar múltiplas versões no cliente.
  • Versões compatíveis: certifique-se de que as dependências compartilhadas são compatíveis entre si para evitar conflitos.

Cache no nível de CDN

Utilizar uma Content Delivery Network (CDN) permite que recursos estáticos sejam entregues mais rapidamente aos usuários, aproveitando o cache distribuído.

  • Configurações de cache-control: ajuste os cabeçalhos HTTP para controlar como e por quanto tempo os recursos devem ser armazenados em cache.
  • Invalidando cache: tenha estratégias para invalidar ou atualizar o cache quando novas versões dos recursos forem implantadas.

Cache no navegador

  • Service workers: implementar cache via Service Workers para um controle mais granular sobre quais recursos são armazenados e quando são atualizados.
  • Preloading e prefetching: antecipar quais recursos serão necessários e carregá-los antecipadamente.

Gerenciando estados globais em aplicações host

Manter um estado global consistente em uma aplicação composta por múltiplos micro front-ends é um desafio.

Estratégias recomendadas

  • Eventos personalizados: utilize o sistema de eventos do navegador para comunicação entre micro front-ends sem criar dependências rígidas.
  • Armazenamento local compartilhado: APIs como Local Storage ou IndexedDB podem servir como meio de compartilhar estado global.
  • Contextos globais: em frameworks como React, pode-se usar Context API, mas deve-se ter cuidado para não introduzir acoplamento indesejado.

Boas práticas

  • Isolamento de domínios: cada micro front-end deve ser responsável por seu próprio estado local e apenas interagir com o estado global quando necessário.
  • Contratos bem definidos: estabeleça interfaces claras para a comunicação entre componentes, facilitando a manutenção e evolução.

Padronização e equipes de plataforma

Enquanto micro front-ends abordam a escalabilidade técnica, a padronização de código e a existência de equipes de plataforma são cruciais para a escalabilidade humana das equipes de desenvolvimento.

O papel das equipes de plataforma

  • Definição de bons padrões: criar e manter padrões de código que facilitam o trabalho das equipes.
  • Ferramentas e infraestrutura: desenvolver ferramentas que automatizam tarefas repetitivas e garantem a qualidade do código.
  • Facilitar a colaboração: garantir que diferentes equipes possam trabalhar juntas de forma eficiente.

Importância da padronização

  • Onboarding mais rápido: novos desenvolvedores se adaptam mais rapidamente a um código padronizado.
  • Qualidade consistente: reduz a incidência de bugs e problemas de manutenção.
  • Facilita a revisão de código: code reviews são mais eficazes quando há um estilo consistente.

Evitando complexidade desnecessária

  • Simplicidade como padrão: optar por soluções simples que resolvem os problemas sem adicionar complexidade excessiva.
  • Decisões baseadas em valor: implementar tecnologias e padrões que trazem benefícios claros para o negócio e para a equipe.
  • Cuidado com o “hype” tecnológico: nem toda nova biblioteca ou framework é adequada para o contexto da sua aplicação.

Leis organizacionais aplicadas ao código

A Lei de Conway afirma que a estrutura de um sistema reflete a estrutura da organização que o desenvolve. Portanto, alinhar a arquitetura técnica com a organização das equipes não é apenas benéfico, mas essencial.

  • Estruturas alinhadas: equipes autônomas responsáveis por micro front-ends específicos refletem uma arquitetura modular.
  • Comunicação eficiente: menos dependências entre equipes reduzem a necessidade de comunicação constante e alinhamentos complexos.
  • Evolução contínua: uma organização flexível permite que a arquitetura evolua com as necessidades do negócio.

Como começar

  • Projeto piloto: implementar um micro front-end em uma parte não crítica do sistema para entender os desafios e benefícios.
  • Definir padrões: estabelecer convenções claras desde o início para rotas, comunicação e estilos.
  • Investir em observabilidade: ferramentas de monitoramento são essenciais para identificar problemas rapidamente.
  • Documentação e comunicação: manter uma documentação atualizada e promover a comunicação entre as equipes para compartilhar aprendizados.

Conclusão

Escalar front-ends de forma eficaz requer uma combinação de soluções técnicas e organizacionais. Arquiteturas de micro front-ends oferecem um caminho para lidar com a complexidade técnica, enquanto a padronização e as equipes de plataforma abordam os desafios humanos de colaboração em larga escala.

No Nubank, entendemos que a inovação contínua e a adaptabilidade são essenciais para oferecer a melhor experiência aos nossos clientes. Seja adotando tecnologias avançadas ou reestruturando nossas equipes, estamos comprometidos em evoluir e enfrentar os desafios de escala do mundo moderno.

Quer fazer parte desse desafio? Estamos sempre em busca de talentos apaixonados por tecnologia e inovação para construirmos, juntos, o futuro roxo!

Para mais insights como esses, assista a gravação do meetup de Engenharia:

Conheça nossas oportunidades