Conformidade no ecossistema de framework JavaScript
Na nossa postagem de introdução do blog, abordamos como aprendemos muito ao criar e usar frameworks e ferramentas para desenvolver e manter aplicativos da Web em grande escala, como a Pesquisa Google, o Maps, o Fotos e assim por diante. Ao proteger os desenvolvedores de escrever código que pode afetar negativamente a experiência do usuário, provamos que os frameworks podem ter um papel fundamental na mudança de resultados para desempenho e qualidade do aplicativo.
No Google, usamos o termo "Conformidade" para descrever essa metodologia. Este artigo aborda como planejamos disponibilizar esse conceito como código aberto para o ecossistema de frameworks JavaScript.
O que é conformidade?
No Google, a conformidade foi uma evolução. As equipes contavam com um pequeno grupo de mantenedores com muita experiência que faziam revisões de código extensas, sinalizando coisas que afetavam a qualidade e a manutenção do app além de problemas de correção. Para ampliar isso para equipes crescentes de desenvolvedores de apps, um sistema de conformidade foi desenvolvido para codificar as práticas recomendadas de maneira automatizada e aplicável. Isso garantiu um nível consistentemente alto de qualidade do app e de manutenção da base de código, independente do número de colaboradores.
A conformidade é um sistema que garante que os desenvolvedores permaneçam no caminho certo. Ela aumenta a confiança e garante resultados previsíveis. Isso torna as equipes produtivas e se torna crucial para a escala, à medida que as equipes crescem e mais recursos são desenvolvidos simultaneamente. Ele permite que os desenvolvedores se concentrem na criação de recursos do produto, liberando-os de detalhes e do cenário em constante mudança em várias áreas, como desempenho, acessibilidade, segurança etc. Qualquer pessoa pode desativar a Conformance a qualquer momento, e ela precisa ser personalizável para que as equipes tenham a opção de aplicar o que decidirem se comprometer.
A conformidade é baseada em padrão fortes e na disponibilização de regras úteis que podem ser aplicadas no momento da criação. Isso se divide nos três princípios a seguir.
1. Padrões fortes
Um aspecto fundamental da conformidade é garantir que as ferramentas usadas pelos desenvolvedores tenham padrões fortes implementados. Isso significa que as soluções não são apenas integradas a frameworks, mas também os padrões de design de framework facilitam a execução da coisa certa e dificultam o acompanhamento de antipadrões. O framework oferece suporte a desenvolvedores com design de aplicativos e estrutura de código.
Para melhorar a performance de carregamento, todos os recursos (fontes, CSS, JavaScript, imagens etc.) precisam ser otimizados. Esse é um desafio complexo que envolve o corte de bytes, a redução de ida e volta e a separação do que é necessário para a primeira renderização, a prontidão visual e a interação do usuário. Por exemplo, extrair CSS crítico e definir prioridade em imagens importantes.
2. Regras acionáveis
Mesmo com as otimizações básicas em vigor, os desenvolvedores ainda precisam fazer escolhas. Há uma gama de possibilidades de otimizações quando se trata de quanto de entrada do desenvolvedor é necessária:
- Padrões que não exigem entrada do desenvolvedor, como o inline CSS crítico.
- Exija a ativação do desenvolvedor. Por exemplo, usar um componente de imagem fornecido pelo framework para dimensionar e redimensionar imagens.
- Exija a ativação e a personalização do desenvolvedor. Por exemplo, marcar imagens importantes para serem carregadas cedo.
- Não é um recurso específico, mas coisas que ainda exigem uma decisão do desenvolvedor. Por exemplo, evitando fontes ou scripts síncronos que atrasam a renderização antecipada.
As otimizações que exigem uma decisão dos desenvolvedores representam um risco para o desempenho do aplicativo. À medida que os recursos são adicionados e a equipe cresce, nem mesmo os desenvolvedores mais experientes conseguem seguir o ritmo das práticas recomendadas em constante mudança, nem é o melhor uso do tempo deles. Para conformidade, regras acionáveis adequadas são tão importantes quanto padrões fortes para garantir que o aplicativo continue a atender a um determinado padrão, mesmo quando os desenvolvedores continuam fazendo mudanças.
3. Tempo de criação
É importante detectar e evitar problemas de desempenho no início do ciclo de desenvolvimento. O tempo de criação, antes de o código ser confirmado, é ideal para detectar e resolver problemas. Quanto mais tarde um problema for detectado no ciclo de desenvolvimento, mais difícil e caro será solucioná-lo. Embora isso se aplique a problemas de correção, também é verdade para problemas de desempenho, já que muitos desses problemas não serão resolvidos retroativamente após a confirmação na base de código.
Atualmente, a maioria dos feedbacks de desempenho é fora da banda por meio de documentação, auditorias únicas ou é exibida tarde demais pela regressão de métricas após a implantação na produção. Queremos trazer isso para o tempo de criação.
Conformidade em frameworks
Para manter um alto nível de experiência do usuário para a performance de carregamento, é necessário responder às seguintes perguntas:
- O que constitui o carregamento ideal e quais são os problemas comuns que podem afetar negativamente?
- Quais soluções podem ser integradas sem a necessidade de entrada do desenvolvedor?
- Como podemos garantir que o desenvolvedor use essas soluções e as aproveite da melhor forma possível?
- Quais outras escolhas o desenvolvedor pode fazer que afetam a performance de carregamento?
- Quais são os padrões de código que podem nos informar sobre essas escolhas (nº 3 e 4 acima) no início da criação?
- Quais regras podemos formular para avaliar esses padrões de código? Como elas podem ser exibidas ao desenvolvedor no momento da criação, mas integradas perfeitamente ao fluxo de trabalho?
Para trazer o modelo de conformidade que temos internamente no Google para frameworks de código aberto, nossa equipe fez várias experiências no Next.js e estamos animados para compartilhar nossa visão e planos refinados. Percebemos que o melhor conjunto de regras que pode avaliar padrões de código precisa ser uma combinação de análise estática de código e verificações dinâmicas. Essas regras podem abranger várias plataformas, incluindo:
- ESLint
- TypeScript
- Verificações dinâmicas no servidor de desenvolvimento do usuário (após a criação do DOM)
- Bundler de módulo (webpack)
- Ferramentas de CSS (ainda em fase de testes)
Ao usar regras em diferentes ferramentas, podemos garantir que elas sejam coesivas, mas também que englobem problemas de experiência do usuário que afetam diretamente o desempenho de carregamento. Além disso, essas regras também podem ser exibidas para os desenvolvedores em momentos diferentes:
- Durante o desenvolvimento local no servidor de desenvolvimento, o navegador e o ambiente de desenvolvimento integrado do usuário vão mostrar avisos, pedindo que os desenvolvedores façam pequenas alterações no código.
- No momento da criação, os problemas não resolvidos vão ser mostrados novamente no terminal do usuário.
Em resumo, as equipes vão escolher os resultados que são importantes para elas, como as Core Web Vitals ou a performance de carregamento, e ativar conjuntos de regras relevantes para que todos os colaboradores de código sigam.
Embora isso funcione muito bem para novos projetos, não é fácil atualizar bases de código grandes para obedecer a regras completas. No Google, temos um sistema extenso para desativar em diferentes níveis, como linhas individuais de código-fonte, diretórios inteiros, bases de código legados ou partes do app que não estão em desenvolvimento ativo. Estamos analisando estratégias eficazes para oferecer isso às equipes que usam frameworks de código aberto.
Conformidade no Next.js
O ESLint é muito usado entre os desenvolvedores de JavaScript, e mais de 50% dos aplicativos Next.js usam o ESLint em alguma parte do fluxo de trabalho de build. A Next.js v11 introduziu o suporte pronto para uso do ESLint, que inclui um plug-in personalizado e configuração compartilhável para facilitar a detecção de problemas comuns específicos do framework durante o desenvolvimento e o build. Isso pode ajudar os desenvolvedores a corrigir problemas significativos no momento da criação. Exemplos incluem quando um determinado componente é usado ou não de uma maneira que possa prejudicar o desempenho, como em Nenhum link HTML para a página. Ou se uma determinada fonte, folha de estilo ou script pode afetar negativamente o carregamento de recursos em uma página. Por exemplo, Nenhum script síncrono.
Além do ESLint, a verificação de tipo integrada no
desenvolvimento e na produção tem suporte no Next.js desde a v9 com suporte ao TypeScript. Vários
componentes fornecidos pelo framework (Image, Script, Link) foram criados como uma extensão de elementos
HTML (<img>
, <script>
, <a>
) para oferecer aos desenvolvedores uma abordagem eficiente para adicionar
conteúdo a uma página da Web. A verificação de tipo oferece suporte ao uso adequado desses recursos, garantindo que
as propriedades e opções atribuídas estejam no escopo aceitável de valores e tipos compatíveis. Confira um
exemplo em largura e altura de imagem necessárias.
Como mostrar erros com avisos e sobreposições
Como mencionado anteriormente, as regras de conformidade podem ser exibidas em várias áreas. As mensagens e sobreposições estão sendo exploradas como uma maneira de mostrar erros diretamente no navegador no ambiente de desenvolvimento local do usuário.
Muitas ferramentas de verificação de erros e auditorias que os desenvolvedores usam (Lighthouse, guia "Issues" do Chrome DevTools) são passivas e exigem alguma forma de interação do usuário para recuperar informações. Os desenvolvedores tendem a agir quando os erros são mostrados diretamente nas ferramentas existentes e quando fornecem ações concretas e específicas que precisam ser tomadas para corrigir o problema.
Conformidade em outros frameworks
A conformidade está sendo explorada no Next.js primeiro com o objetivo de expandir para outros frameworks (Nuxt, Angular etc.). O ESLint e o TypeScript já são usados em muitos frameworks de várias maneiras diferentes, mas o conceito de um sistema de execução coeso no nível do navegador está sendo explorado ativamente.
Conclusão
A conformidade codifica as práticas recomendadas em conjuntos de regras que podem ser usadas pelos desenvolvedores como padrões de código simples. A equipe do Aurora se concentrou na performance de carregamento, mas outras práticas recomendadas, como acessibilidade e segurança, são igualmente aplicáveis.
Seguir as regras de conformidade deve resultar em resultados previsíveis, e alcançar uma alta barra de experiência do usuário pode se tornar um efeito colateral da criação da sua pilha de tecnologia. A conformidade torna as equipes produtivas e garante um nível de alta qualidade para o aplicativo, mesmo que as equipes e as bases de código cresçam com o tempo.