Conformidade no ecossistema do framework do JavaScript
Na nossa postagem introdutória do blog, falamos sobre 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 contra a escrita de códigos que podem afetar negativamente a experiência do usuário, provamos que os frameworks podem desempenhar um papel fundamental na mudança dos resultados para desempenho e qualidade do aplicativo.
Internamente no Google, usamos o termo "Conformidade" para descrever essa metodologia, e este artigo aborda como planejamos abrir o código desse conceito para o ecossistema do framework JavaScript.
O que é conformidade?
No Google, a Conformance foi uma evolução. As equipes contaram com um pequeno conjunto de mantenedores experientes que fizeram extensas revisões de código, sinalizando coisas que afetaram a qualidade e a capacidade de manutenção do aplicativo muito além dos problemas de correção. Para escalonar isso para equipes cada vez maiores de desenvolvedores de apps, um sistema de conformidade foi desenvolvido para codificar as práticas recomendadas de maneira automatizada e aplicada. Isso garantiu um alto padrão consistente na qualidade do app e na manutenção da base de código, independentemente do número de colaboradores do código.
A conformidade é um sistema que garante que os desenvolvedores permaneçam no caminho certo, cria confiança e garante resultados previsíveis. Isso torna as equipes produtivas e se torna crucial para o escalonamento, à 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 das minúcias e do cenário dinâmico em várias áreas, como desempenho, acessibilidade, segurança etc. Qualquer pessoa pode desativar a conformidade a qualquer momento e ele precisa ser personalizável na medida em que as equipes tenham a opção de aplicar o que quiserem.
A conformidade é baseada em padrões fortes e fornece regras acionáveis 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 que os desenvolvedores usam tenham padrões fortes. Isso significa que as soluções não são apenas incorporadas a frameworks, mas também padrões de design de framework facilitam fazer a coisa certa e dificultam seguir os antipadrões. O framework oferece suporte a desenvolvedores com design de aplicativo e estrutura de código.
Para o desempenho do carregamento, todos os recursos (fontes, CSS, JavaScript, imagens etc.) devem ser otimizados. Esse é um desafio complexo que envolve o corte de bytes, a redução de idas e voltas 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 essenciais e definir a prioridade de imagens importantes.
2. Regras acionáveis
Mesmo com as otimizações de base em vigor, os desenvolvedores ainda precisam fazer escolhas. Há um espectro de possibilidades de otimizações quando se trata de quanta contribuição do desenvolvedor é necessária:
- Padrões que não exigem entradas do desenvolvedor, como a inserção in-line de CSS essencial.
- Exige a ativação do desenvolvedor. Por exemplo, usar um componente de imagem fornecido pelo framework para dimensionar e dimensionar imagens.
- Exigem a ativação e personalização do desenvolvedor. Por exemplo, marcar imagens importantes para serem carregadas antecipadamente.
- Não é um recurso específico, mas itens que ainda exigem decisão do desenvolvedor. Por exemplo, evitar fontes ou scripts síncronos que atrasam a renderização antecipada.
Otimizações que exigem qualquer decisão dos desenvolvedores representam um risco para o desempenho do aplicativo. À medida que recursos são adicionados e sua equipe escalona, mesmo os desenvolvedores mais experientes não conseguem acompanhar as práticas recomendadas em constante mudança, nem é o melhor uso do tempo. Para conformidade, regras acionáveis adequadas são tão importantes quanto padrões fortes para garantir que o aplicativo continue atendendo a um determinado padrão, mesmo quando os desenvolvedores continuarem a fazer alterações.
3. Tempo de criação
É importante detectar e impedir problemas de desempenho no início do ciclo de vida do desenvolvimento. O tempo de criação, antes do comprometimento do código, é ideal para detectar e resolver problemas. Quanto mais tarde um problema for detectado no ciclo de vida de desenvolvimento, mais difícil e mais caro será resolvido. Embora isso se aplique a problemas de correção, isso também se aplica a problemas de desempenho, já que muitos desses problemas não serão resolvidos retroativamente depois de confirmados na base de código.
Atualmente, a maior parte do feedback de desempenho é fora de banda por meio de documentação, auditorias pontuais ou é revelada tardiamente por meio da regressão de métricas após a implantação para produção. Queremos trazer isso para o momento da criação.
Conformidade em frameworks
Para manter um alto padrão de experiência do usuário em relação ao desempenho de carregamento, as seguintes perguntas precisam ser respondidas:
- O que constitui o carregamento ideal e quais são os problemas comuns que podem afetá-lo negativamente?
- Quais soluções podem ser integradas que não precisam da contribuição do desenvolvedor?
- Como podemos garantir que o desenvolvedor use essas soluções e as aproveite da maneira ideal?
- Que outras escolhas o desenvolvedor pode fazer que afetam o desempenho de carregamento?
- Quais são os padrões de código que podem nos informar sobre essas opções (no 3 e no 4 acima) no início do momento da criação?
- Que regras podemos formular para avaliar esses padrões de código? Como eles podem ser apresentados ao desenvolvedor no momento da criação e integrados ao fluxo de trabalho?
Para levar o modelo de conformidade que temos internamente no Google para frameworks de código aberto, nossa equipe fez muitos testes no Next.js, e estamos felizes em compartilhar nossa visão e nossos planos refinados. Percebemos que o melhor conjunto de regras para avaliar padrões de código precisa ser uma combinação de análise de código estático 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 exploratórias)
Ao fornecer regras por diferentes ferramentas, podemos garantir que elas sejam coesas, mas também englobam problemas de experiência do usuário que afetam diretamente o desempenho de carregamento. Além disso, essas regras também podem ser exibidas aos desenvolvedores em momentos diferentes:
- Durante o desenvolvimento local no servidor de desenvolvimento, o navegador e o ambiente de desenvolvimento integrado do usuário exibem avisos, pedindo que os desenvolvedores façam pequenas mudanças no código.
- No momento da criação, os problemas não resolvidos aparecem de novo no terminal do usuário.
Em resumo, as equipes escolhem os resultados que consideram importantes, como Core Web Vitals ou desempenho de carregamento, e ativam conjuntos de regras relevantes para todos os colaboradores do código seguirem.
Embora isso funcione muito bem para projetos novos, não é fácil fazer upgrade de grandes bases de código para obedecer a conjuntos de regras completos. No Google, temos um amplo sistema de desativação em diferentes níveis, como linhas individuais de código-fonte, diretórios inteiros, bases de código legadas ou partes do app que não estão em desenvolvimento ativo. Estamos explorando ativamente estratégias eficazes para levar isso às equipes que usam frameworks de código aberto.
Conformidade no Next.js
O ESLint é amplamente usado entre desenvolvedores de JavaScript, e mais de 50% dos apps Next.js usam o ESLint em alguma parte do fluxo de trabalho de build. O Next.js v11 introduziu suporte a ESLint pronto para uso, 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. Por exemplo, quando um determinado componente é usado ou não, de uma maneira que pode prejudicar o desempenho, como em Nenhum link HTML para a página. ou se uma 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 (link em inglês) no
desenvolvimento e na produção é compatível com o Next.js desde a v9 com TypeScript. Vários
componentes fornecidos pelo framework (imagem, script, link) foram criados como uma extensão de elementos
HTML (<img>
, <script>
, <a>
) para oferecer aos desenvolvedores uma abordagem eficiente na hora de adicionar
conteúdo a uma página da Web. A verificação de tipo permite o 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 de largura e altura da imagem obrigatórios.
Exibição de erros com avisos e sobreposições
Como mencionado anteriormente, as regras de conformidade podem ser exibidas em várias áreas. No momento, avisos e sobreposições estão sendo analisados como uma forma de exibir erros diretamente no navegador dentro do ambiente de desenvolvimento local do usuário.
Muitas ferramentas de verificação de erros e auditoria usadas pelos desenvolvedores (Lighthouse, guia "Problemas do Chrome DevTools") são passivas e exigem alguma forma de interação do usuário para recuperar informações. É mais provável que os desenvolvedores ajam quando os erros aparecem diretamente nas ferramentas existentes e quando eles fornecem ações concretas e específicas que precisam ser tomadas para corrigir o problema.
Conformidade em outras estruturas
Estamos analisando a conformidade primeiro no Next.js 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 ambiente 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 acionáveis para desenvolvedores como padrões de código simples. A equipe do Aurora se concentrou no desempenho de carregamento, mas outras práticas recomendadas, como acessibilidade e segurança, também se aplicam.
Seguir as regras de conformidade precisa gerar resultados previsíveis. Além disso, alcançar um alto padrão de experiência do usuário pode ser um efeito colateral de criar seu conjunto de tecnologias. A conformidade torna as equipes produtivas e garante um padrão de alta qualidade para o aplicativo, mesmo à medida que as equipes e as bases de código crescem ao longo do tempo.