Arquitetura de front-end em escala para grandes organizações

(Daniel Ostapenko) ( 14 de outubro de 2020)

Olá! Quero discutir com você como gerenciar a arquitetura de front-end em grandes organizações. Parece-me que não há muitos artigos sobre este assunto e não é bem explicado.

Por grande organização neste artigo, quero dizer empresas, nas quais o número de engenheiros de front-end começa a ser maior que 15 e a empresa tem pelo menos vários projetos de front-end.

Não quero discutir problemas de gerenciamento ou de domínio de negócios, aqueles que são comumente vistos em empresas tão grandes, mas vamos nos concentrar apenas na arquitetura de front-end.

A arquitetura de front-end está envolvida em muitas áreas hoje em dia, então, para começar, eu proporia dividi-la nas seguintes seções:

Esquema de arquitetura de frontend

1. Código Visual

Vamos começar pelo tópico mais fácil, na minha opinião, é o código visual de nossos aplicativos.

Provavelmente porque desenvolvemos vários aplicativos de front-end na mesma empresa que os queremos para ter:

  • reconhecimento da marca
  • a mesma UI / UX

Para conseguir isso, precisamos ter um sistema de design. A equipe de design deve criar o sistema de design e seguir essas diretrizes em todos os designs de produtos futuros. Mesmo esta já é uma tarefa muito complexa e precisa de muitas discussões e alinhamentos entre a equipe de design, engenheiros e produto.

Do ponto de vista do front-end, precisamos fornecer uma ferramenta para implementar e compartilhar este sistema de design entre engenheiros. Uma boa solução para isso pode ser a criação do pacote npm, que será representado visualmente por um Storybook ou alguma ferramenta semelhante. Na minha opinião, é muito importante ter um recurso web dedicado (com URL) com documentação sobre como usar este pacote. Este recurso web será usado por engenheiros de front-end e por designers e pode ser um ótimo ponto de referência em conversas entre eles.

Código visual

Resumo:

Neste momento, temos um sistema de design e sua representação em um pacote e documentação interativa para ele. Compartilhamos e adotamos este pacote em todos os nossos aplicativos front-end.

2. Estrutura do código

Vamos conversar um pouco sobre a engenharia diária. Implementamos novos recursos, corrigimos bugs e refatoramos o código, se necessário. Nós nos preocupamos com nossa base de código, tentando torná-la agradável e facilmente compreensível. Mas o que acontece quando passamos a ter não 1, não 2, mas dezenas de pequenos ou grandes projetos na empresa? Normalmente, as pessoas se agrupam em torno de alguns dos projetos e passam a trabalhar apenas com esse grupo de projetos. Por nossa natureza humana e o tempo limitado, geralmente, não podemos “cuidar de mais de 2–3–5 projetos em um período de tempo. Então, naturalmente, começamos a ter aqueles grupos de influências. A propósito, obrigado à NASA por uma foto tão incrível para minha analogia 😃

Grupos de influências

Mas, começamos a ter mais e mais casos, quando as pessoas se cruzam colaborações de equipes, precisam verificar o código e as soluções uns dos outros, corrigir alguns bugs até mesmo em outros aplicativos ou adicionar algo que eles precisam dentro de algum aplicativo externo (externo para seu grupo de influência). A má notícia – que esse processo está acontecendo em grandes empresas quase descontrolado. A boa notícia – podemos ajudar a melhorá-la.

Como? Corrigir. Ao fornecer a mesma estrutura de código , codificação e diretrizes de estruturação para todos os projetos na empresa.

Vamos nos aprofundar no que entendemos por estrutura de código:

  • A estrutura de pastas no projeto
    Quando os engenheiros entram em um novo projeto pela primeira vez – tendo a mesma estrutura de pastas em seus projeto, onde eles sabem que tudo ajuda muito a navegar e pesquisar.
  • Arquivos de configuração ou de suporte
    Arquivos como package.json, .gitignore, .editorconfig, webpack.config, etc. Devem estar sempre no mesmo lugar, em todos os projetos.O mesmo está conectado aos arquivos de configuração de testes ou arquivos CI, caso sejam necessários.
  • Localização fixa dos tipos de arquivo
    Se a localização dos mesmos tipos de arquivo estiver seguindo sempre a mesma estrutura também funciona muito bem. Por exemplo, se a pasta do componente sempre tiver um style.css arquivo:
/Component
--/Component.tsx
--/style.css
--/index.ts
  • Estrutura interna dos componentes
    A estrutura dentro dos arquivos deve ser a mesma: ordem das importações, exportações, a posição da função pública , tipos, etc. Em cada tipo de arquivo, você deve saber o que esperar.
  • Convenções de nomenclatura
    Isso inclui nomes de pastas, arquivos, variáveis, funções, classes, tipos, etc.
  • Convenções de codificação
    Em geral, eu diria que as convenções de codificação são uma seção muito ampla, mas aqui eu só quero incluir coisas que não cabem no resto das seções, como ; ou not ; 😁 e semelhantes .

A mesma estrutura de código e o conjunto de ferramentas do projeto na prática são muito estreitos juntos er e ajudar uns aos outros a coexistir. Por conjunto de ferramentas, quero dizer ferramentas CLI (inicialização de projeto, linting, teste, etc.), extensões IDE, etc. Discutiremos o tópico de conjunto de ferramentas nas próximas seções.

Estrutura do código

Resumo:

Depois de aplicar esta seção e adotá-la, devemos ter todos os projetos em toda a organização com a mesma estrutura de pastas, diretrizes de nomenclatura, estrutura de arquivos, etc. Todos os desenvolvedores idealmente, pode saltar para qualquer outro projeto e não ficar completamente perdido nele. Este “completamente perdido” também está muito conectado à pilha de tecnologia que é usada dentro do projeto, então vamos falar sobre isso.

3. Pilha de tecnologia

Semelhante à anterior seção, queremos ter uma pilha de tecnologia unificada em todos os projetos da organização. O motivo para isso é muito semelhante – queremos que nossos engenheiros se sintam confortáveis ​​com todos os projetos da empresa.

Em projetos de front-end, os componentes da pilha de tecnologia podem ser: estrutura, com base na construção do projeto, linguagem principal, processador de estilos, camada de dados (ex. Apollo), gerenciamento de estado, testes, linting de código, sistema de construção e outros.

Claro, em todas as regras há exceções. E neste tópico, eu também gostaria de fazer uma observação, que às vezes algumas tecnologias se encaixam extremamente em alguns projetos específicos, mesmo que essas tecnologias não façam parte da pilha de tecnologia global da empresa. Mas, ainda assim, a cada vez que essa ideia se afasta da comunicação Você deve pensar duas vezes porque o custo de suporte a essas coisas é muito alto, então os benefícios devem ser dramáticos.

Vamos mencionar aqui alguma pilha de tecnologia genérica que pode caber agora na maioria dos projetos ( é claro que cobre apenas parte da pilha de tecnologia real, mas pode ser um bom ponto de partida para alguém 🤷):

Pilha

Depois que definimos a pilha de tecnologia em nossa empresa e concordamos com ela, há também outros pilares muito importantes de sucesso .

Primeiro – precisamos anote a pilha de tecnologia no documento . O documento, que deve ser bem e facilmente compartilhado entre engenheiros , para que eles sempre possam fornecer um link um para o outro como prova.

Em segundo lugar – devemos escrever novamente e compartilhar o documento da maneira como os novos projetos devem ser iniciados e inicializados, usando a pilha de tecnologia definida .

Pilha de tecnologia

Resumo:

Depois de implementar e adotar tudo o que mencionamos acima, você deve tenha todos os seus projetos na organização para compartilhar a mesma pilha de tecnologia. Idealmente, sem quaisquer diferenças. Não idealmente – com diferenças insignificantes. Se adicionarmos também a seção anterior, o código, as pastas, a estrutura de arquivos também devem ser quase idênticos em seus projetos.Portanto, navegar por qualquer projeto deve ser uma tarefa muito fácil. Bom 😊

4. Ferramentas

Este tópico é muito importante. Usamos algumas ferramentas adicionais agora em quase todos os lugares – para linting, construção de nossos aplicativos, CI, geradores de componentes e muito mais. É por isso que vejo se podemos escolher as ferramentas corretas para nossos projetos – é crucial. Ferramentas boas versus ferramentas ruins (ou nenhuma ferramenta), é o mesmo que uma comparação entre automação e teste manual .

Acabamos de falar nas seções anteriores sobre pilha de tecnologia e estrutura de código e mencionamos que precisamos escrever muita documentação para fazer com que as pessoas os sigam. Mas o conjunto de ferramentas correto pode dar a você a oportunidade de automatizar seguindo as diretrizes de sua empresa .

Para Por exemplo, se você tem um estilo de codificação especificado – você pode dar às pessoas o conjunto de ferramentas de linting, que por padrão segue essas regras. Se você tiver a pilha de tecnologia definida, uma boa ferramenta CLI lhe dará a oportunidade de inicializar um novo projeto com essas tecnologias específicas de sua pilha de tecnologia em vigor.

Vamos tentar discutir quais partes do sua arquitetura de front-end pode ser coberta por ferramentas:

  • Estilo e estrutura do código
    Como discutimos antes, isso pode ser facilmente automatizado por ferramentas
  • Inicialização do projeto
    Você não ” não é necessário criar uma nova estrutura de projeto, instalando manualmente todos os pacotes necessários, etc.
  • Geração de componentes
    Na maioria das vezes, algum componente em seu aplicativo não contém um único arquivo, portanto, a criação de arquivos, vinculá-los / importá-los pode levar tempo, portanto, pode ser automatizado.
  • Iniciar e construir
    Obviamente, a coisa mais óbvia de ser automática mate – como você constrói ou inicia seu aplicativo.
  • Testes
    O processo de construção de seu aplicativo para testes e realmente executando todos os tipos de testes – unidade, integração, etc.
  • Gerenciamento de dependências
    Como sabemos, cerca de 80\% do nosso código agora são dependências. Portanto, precisamos mantê-los atualizados e gerenciar isso em uma grande empresa não é uma coisa fácil de fazer.
  • Dependências entre projetos
    Muito provavelmente nossos projetos não estão funcionando isoladamente e podem depender de outros projetos ou ser uma dependência de algum outro projeto, portanto, podemos precisar de algumas ferramentas para facilitar o processo de vinculá-los, desenvolver em uma combinação de vários projetos (como Bit , por exemplo), etc.
  • CI
    CI é uma parte essencial de nosso conjunto de ferramentas de base diária, e a automação e a unificação dele podem ser um trabalho muito benéfico para sua organização.

Se você não deseja desenvolver um novo conjunto de ferramentas próprio, posso recomendar o conjunto de ferramentas NX , como um dos candidatos mais interessantes. , parece que os criadores do Babel fizeram uma solução semelhante, que você pode querer verificar – Roma . Essas ferramentas não cobrem tudo, mas uma grande parte do que falamos, então pode ser um bom ponto de partida.

Ferramentas

Resumo:

Imagine como nossa arquitetura pode se tornar ótima depois de concluirmos todas as seções e aprovarmos 🧙

Cada projeto é o mesmo e mantido e gerenciado pelo conjunto de ferramentas unificado. Cada projeto pode ser iniciado e construído da mesma maneira. Novos componentes são gerados no mesmo lugar e com as mesmas diretrizes de nomenclatura.

Mas isso é “legal” ou tem desvantagens? Como acontece com qualquer solução, ela tem desvantagens. Um deles – precisa de algum tempo para a integração de novos engenheiros à sua empresa. Mas se tudo for feito de uma maneira muito natural (como as pessoas já se acostumaram com outras ferramentas existentes) e documentado, então isso não se torna um grande problema quando você compara com os benefícios da velocidade de desenvolvimento, uma oportunidade para os engenheiros trabalharem qualquer base de código facilmente, etc.

5. Produção

Sobre esta parte da arquitetura de front-end, geralmente, os engenheiros cuidam de menos.Talvez porque não esteja conectado com a codificação em si na maioria das vezes🤷 e provavelmente não é tão empolgante, mas não menos importante ☝️

Na produção, geralmente precisamos cuidar das próximas coisas:

  • Analytics
    Todos os tipos de eventos de rastreamento diferentes etc. Coisas como Google Analytics , Segmento , HotJar , etc.
  • Monitoramento de status
    Isso inclui coisas, como verificações de saúde, podem ser até mesmo testes executados em produção, relatórios de erros (como Sentinela ), etc.
  • Desempenho
    É um pouco semelhante ao item anterior, mas mais orientado para o desempenho. Isso inclui medir o tempo de resposta, a primeira pintura significativa etc. (provavelmente a ferramenta nº 1 – Farol )
  • Teste A / B
    Todos os tipos de soluções de teste A / B ou sinalizadores de recursos.
  • Cache
    Ferramentas como Verniz , Cloudflare .

Todos eles podem ser unificados em seus aplicativos front-end na empresa, o que simplificará a vida de seus engenheiros . Por exemplo, adicionando pacotes com as configurações iniciais predefinidas e adicionando esses pacotes ao seu projeto de inicialização.

Outra parte da produção é a preparação do código, como:

  • Minificação
    Minificação apenas do código 😄
  • Mapeamento de origem
    Mapas de origem também podem ser necessários para algumas outras ferramentas, como Sentry.
  • Preparação de ativos
    Preparação para telas com diferentes resoluções, recorte de imagens, etc.

Esses são ótimos candidatos para serem adicionados o conjunto de ferramentas que temos para gerenciar aplicativos front-end, sobre o qual falamos na seção Ferramentas.

Produção

Resumo:

Idealmente, todos aqueles deveriam ser adicionado a cada projeto de front-end por padrão na fase de bootstrapping. E os engenheiros se preocupariam apenas em adicionar chaves de API corretas nos lugares corretos para as ferramentas.

6. Desenvolvimento

Ferramenta CLI

Parcialmente, já discutimos a experiência de desenvolvimento na seção Ferramentas, quando tocamos na ferramenta CLI de front-end. Ferramentas unificadas são uma grande parte dos engenheiros “diariamente, mas não tudo.

API

Uma API confortável para trabalhar localmente é a segunda coisa incrível que podemos fazer para melhorar o desenvolvedor experiência e a velocidade de desenvolvimento. Normalmente servir API localmente para engenheiros de front-end não é um processo trivial: isso pode incluir a instalação de ferramentas ou estruturas, com as quais eles podem não estar familiarizados. Mesmo se a configuração encaixada, isso pode exigir uma grande quantidade de computação recursos das máquinas do desenvolvedor (se não for – isso pode ser considerado uma configuração). O que pode ser uma solução neste caso – API servida externamente. Isso pode ser um único servidor para todos os engenheiros ou algum mecanismo de bootstrap facilmente seu próprio servidor dedicado para desenvolvimento.

CI

CI é a terceira grande parte. Posso supor que sua empresa já escolheu alguma ferramenta de CI para front-end e usa esta única ferramenta (ex. Círculo CI ,

Concourse CI ou qualquer outro). Se não, você deve unificar isso.

A configuração de CI do projeto em particular, na minha opinião, deve ser parte do trabalho da equipe que está trabalhando no projeto. Isso dá chances de o CI ser estável porque há pessoas interessadas em trabalhar, usando-o todos os dias, e têm o poder e as habilidades para consertá-lo, configurá-lo e aprimorá-lo.

No entanto, nem todo o trabalho deve ser feito pela equipe. Para aplicativos de front-end, existe um grupo bastante específico de tarefas, que podem ser potencialmente necessárias. Especialmente, se pudéssemos conseguir unificar a estrutura de pasta / código, pilha de tecnologia, etc. Então, depois de algum tempo em sua empresa, pode chegar o ponto em que você seria capaz de detectar esses padrões para estágios de sua ferramenta de CI, implementar esses estágios como algum tipo de “blocos de construção” e dar uma oportunidade para que seus engenheiros construam seus pipelines de CI a partir desses “blocos de construção” unificados.

Ambientes de demonstração

E, finalmente, a última – verificação de o recurso implementado.Depois que os engenheiros concluem e implementam tudo – eles quase sempre precisam verificar como é e como funciona e compartilhar isso com outros engenheiros, designers ou outras partes interessadas. Para tais necessidades, funciona muito bem com a versão temporária implantada do seu aplicativo para o PR específico com o URL fornecido.

Aplicativo temporariamente implantado
Aplicativo implantado temporariamente

Esta solução acelera muito a comunicação entre diferentes equipes e pessoas e acho que isso é apenas um must-have. No entanto, esta versão implantada temporariamente deve estar o mais próximo possível da produção, porque também pode ser uma ótima ferramenta para verificar alguns erros de superfície ou bugs.

Isso pode ser facilmente adicionado aos seus projetos e automatizado se seu front-end os pipelines do processo de construção e implantação de aplicativos são unificados. Além disso, ferramentas semelhantes ou semelhantes como Kubernetes e Helm podem ajudar muito na implementação.

Desenvolvimento

Resumo:

Fluxos de desenvolvimento confortáveis ​​e eficientes com uma única ferramenta de CI com blocos de construção para fazer qualquer Pipeline de CI, com ferramentas de front-end CLI unificadas e ambientes de demonstração. Tudo isso deve tornar nosso processo de desenvolvimento o mais suave possível. Multiplique isso pelo número de engenheiros que você tem na empresa e entenderá como isso é benéfico.

7. Modularidade

Este tópico é muito extenso e pode exigir um artigo separado para ser discutido, mas eu tentaria examiná-lo brevemente.

Em grandes organizações, grandes bases de código não são raras coisa. Com todos os problemas conhecidos que vêm junto com eles, como pipelines de CI lentos, problemas com trabalho colaborativo, testes lentos, etc. Portanto, a grande parte da arquitetura de front-end é uma decisão sobre quão granular queremos ver aplicativos / módulos de front-end independentes.

Existem 3 modelos principais que temos agora:

  • Monolith
    Um grande repositório com um único projeto e todo o código lá, todas as equipes estão trabalhando neste repositório juntas ao mesmo tempo.
  • Monorepo
    Muitos projetos, mas ainda um grande repositório ( monorepo no wiki ). Todas as equipes ainda estão trabalhando no mesmo repositório, mas com projetos diferentes. Já existem oportunidades para corrigir alguns problemas, que temos com uma abordagem monolítica, executando pipelines apenas para projetos específicos, os projetos têm suítes de teste menores, etc. Ferramentas como Lerna pode tornar sua vida muito mais fácil caso você escolha esta abordagem.
  • Repo por projeto
    Cada projeto tem seu próprio repositório e todas as coisas de suporte, como pipelines de CI, implantações, etc.

Em todos esses modelos, o projeto pode significar um aplicativo front-end independente, página, módulo de front-end independente, etc. Isso depende de quão granular você deseja decidir dividir seus aplicativos de front-end. Na maioria dos casos, essa divisão deve estar em sincronia com a estrutura de organização desejada e gerenciamento de pessoas.

O segundo grande tópico depois de decidir como dividir seu aplicativo será como conectar essas peças (se você decidiu para dividir seu aplicativo).

E aqui temos as próximas abordagens:

  • Composição em tempo de construção
    Seus projetos podem ser apenas pacotes npm, instalados e compostos durante o tempo de compilação.
  • Servidor- composição lateral
    Esta abordagem geralmente inclui a renderização do lado do servidor e a composição que ocorre em um servidor. Ferramentas como o Hypernova podem ajudar a organizá-lo melhor.
  • Composição do lado do cliente
    Composição dos projetos dentro do navegador. No blog de Martin Fowler, há uma explicação muito boa de algumas abordagens – aqui . Além disso, é muito importante mencionar Federação de Módulos , uma nova abordagem introduzida no Webpack 5 .
  • Composição da rota
    Super simples – apenas cada projeto tem sua própria URL e em um “nível Nginx” decidimos para onde redirecionar os usuários.(desculpe por essa explicação 😄 mas achei que seria mais fácil de entender)

Como eu disse antes, é muito difícil cobrir esse tópico em um formato tão pequeno, mas espero que você pelo menos tenha encontrado algumas ideias interessantes para si mesmo e se aprofunde nos tópicos por conta própria 🙏🏻 .

Modularidade

Resumo:

Encontramos uma maneira de deixar nossas equipes felizes e produtivas organizando os repositórios, dividindo nossos projetos em partes menores (provavelmente), tornando as equipes mais independentes umas das outras.

Bem-vindo ao paraíso 😁

8. Teste

Existem tantos recursos disponíveis sobre o teste de aplicativos front-end, então eu tentaria não entrar em detalhes, o que você pode easi encontrar, mas se concentrar mais nos problemas das grandes organizações e como podemos resolvê-los.

O primeiro deles – cada engenheiro entende as técnicas de teste de maneira diferente, também qual técnica aplicar em qual situação, como escrever “ bons ”testes, etc. Portanto, faz muito sentido documentar com bastante precisão todas as nuances e diretrizes dos níveis de teste usados ​​na empresa e as diretrizes para cada um deles.

Os níveis de teste possíveis que você deseja tem em sua estratégia de teste:

  • teste de unidade
  • teste de integração
  • teste E2E
  • … e outros

Além disso, como uma segunda etapa, precisamos unificá-los em diferentes aplicativos de front-end na empresa, para que as pessoas não tenham dúvidas sobre como e o que testar ao mudar para um projeto diferente.

Se você conseguiu unificar os níveis e abordagens de teste, pode ajudar automaticamente a resolver o segundo problema – a configuração da infraestrutura de teste. Cada projeto por si só precisa definir e configurar localmente e em CI alguma infraestrutura de teste. Por exemplo, decidimos que usaremos o Cypress e ele precisa ser executado dentro de uma imagem docker. Isso precisa de algum tempo para ser configurado localmente e no CI. Se multiplicarmos pelo número de projetos que temos – é uma quantidade enorme de tempo. Então, a solução – unificar isso novamente e fornecer algumas ferramentas para os projetos. Parece fácil, mas leva muito tempo para implementar.

Teste de tempo de não desenvolvimento

Eu também queria tocar em outra forma de testar seus aplicativos depois de recursos já implementados e implantados. E sim, monitorar, é claro, faz parte 😁.

Já mencionamos nas seções anteriores o monitoramento de erros e de desempenho para aplicativos de front-end, monitoramento de tempo de atividade, a resposta de diferentes locais.

É ótimo também ter Os testes do Lighthouse são executados no seu site (podem ser incluídos nos pipelines de CI). Para encontrar mais facilmente gargalos de desempenho, problemas de acessibilidade e melhorar a qualidade das páginas da web em geral.

E o último – testes de produção nos fluxos de negócios mais importantes. Provavelmente, eles funcionarão melhor se você executá-los diretamente no produto. no ambiente, mas também pode ser possível uma modificação quando podemos executar tais testes em um ambiente de preparação / teste, que é muito próximo ao de produção ou mesmo espelhando-o. Há um artigo muito bom sobre este tópico – (aqui).

Teste

Resumo:

Temos diretrizes de teste claras com níveis de teste necessários definidos para cada aplicativo front-end. Temos um único pipeline de CI para cada aplicativo e uma única ferramenta CLI, que ajuda a executar testes localmente.

Palavra final

Realmente espero que vocês tenham encontrado algo interessante nisso artigo. Lamento muito que na maioria dos tópicos eu apenas arranhei a superfície dos problemas. E ficaremos felizes em discuti-los mais, então deixe suas perguntas nos comentários ou envie um ping diretamente no twitter – @denieler .