No Google I/O 2018, apresentamos um resumo de ferramentas, bibliotecas e técnicas de otimização que facilitam a melhoria do desempenho da Web. Aqui, explicamos isso usando o app Oodles Theater. Também falamos sobre nossos experimentos com carregamento preditivo e a nova iniciativa Guess.js.
No ano passado, estivemos ocupados tentando descobrir como tornar a Web mais rápida e eficiente. Isso levou a novas ferramentas, abordagens e bibliotecas que gostaríamos de compartilhar com você neste artigo. Na primeira parte, vamos mostrar algumas técnicas de otimização que usamos na prática ao desenvolver o app Oodles Theater. Na segunda parte, vamos falar sobre nossos experimentos com carregamento preditivo e a nova iniciativa Guess.js.
A necessidade de performance
A Internet fica mais pesada a cada ano. Se verificarmos o estado da Web, veremos que uma página média em dispositivos móveis pesa cerca de 1,5 MB, sendo a maioria JavaScript e imagens.
O tamanho crescente dos sites, junto com outros fatores, como latência de rede, limitações de CPU, padrões de bloqueio de renderização ou código de terceiros desnecessário, contribui para o quebra-cabeças complicado de desempenho.
A maioria dos usuários classifica a velocidade como o topo da hierarquia de UX das necessidades deles. Isso não é muito surpreendente, porque você não pode fazer muito até que uma página termine de carregar. Não é possível extrair valor da página nem admirar a estética dela.
![Hierarquia de UX em forma de pirâmide](https://web.dev/static/articles/web-performance-made-easy/image/ux-hierarchy-piramide-9a38f1858336f.png?hl=pt-br)
Sabemos que a performance é importante para os usuários, mas também pode parecer um segredo descobrir por onde começar a otimização. Felizmente, há ferramentas que podem ajudar você.
Lighthouse: uma base para o fluxo de trabalho de performance
O Lighthouse é uma parte do Chrome DevTools que permite fazer uma auditoria do seu site e oferece dicas sobre como melhorá-lo.
Recentemente, lançamos várias novas auditorias de desempenho que são muito úteis no fluxo de trabalho de desenvolvimento diário.
![Novas auditorias do Lighthouse](https://web.dev/static/articles/web-performance-made-easy/image/new-lighthouse-audits-a5c01f6ee0cf4.png?hl=pt-br)
Vamos conferir como aproveitar esses recursos em um exemplo prático: o app Oodles Theater. É um pequeno app da Web de demonstração, em que você pode testar alguns dos nossos Doodles interativos favoritos e até jogar um ou dois jogos.
Ao criar o app, queríamos garantir que ele tivesse o melhor desempenho possível. O ponto de partida para a otimização foi um relatório do Lighthouse.
![Relatório do Lighthouse para o app Oodles](https://web.dev/static/articles/web-performance-made-easy/image/lighthouse-report-oodles-04ce89ae09ebc.png?hl=pt-br)
A performance inicial do nosso app, conforme mostrado no relatório do Lighthouse, foi muito ruim. Em uma rede 3G, o usuário precisava esperar 15 segundos para a primeira pintura significativa ou para o app ficar interativo. O Lighthouse destacou vários problemas com nosso site, e a pontuação de desempenho geral de 23 refletiu exatamente isso.
A página pesava cerca de 3,4 MB.Precisávamos desesperadamente cortar alguns excessos.
Isso deu início ao nosso primeiro desafio de performance: encontrar coisas que podemos remover facilmente sem afetar a experiência geral.
Oportunidades de otimização de performance
Remover recursos desnecessários
Há algumas coisas óbvias que podem ser removidas com segurança: espaços em branco e comentários.
![Benefícios da minificação](https://web.dev/static/articles/web-performance-made-easy/image/gains-minification-209064021d2a2.png?hl=pt-br)
O Lighthouse destaca essa oportunidade na auditoria de CSS e JavaScript não unificados. Estávamos usando o webpack para nosso processo de build. Para conseguir a minificação, simplesmente usamos o plug-in Uglify JS.
A minificação é uma tarefa comum. Por isso, você pode encontrar uma solução pronta para qualquer processo de build que use.
Outra auditoria útil nesse espaço é Ativar a compactação de texto. Não há motivo para enviar arquivos não compactados, e a maioria das CDNs oferece suporte a isso de forma nativa.
Usamos o Firebase Hosting para hospedar nosso código, e o Firebase ativa o gzip por padrão. Assim, por hospedar nosso código em uma CDN razoável, conseguimos isso sem custo financeiro.
Embora o gzip seja uma forma muito conhecida de compactação, outros mecanismos, como Zopfli e Brotli, também estão ganhando força. O Brotli tem suporte na maioria dos navegadores, e você pode usar um binário para pré-compactar seus recursos antes de enviá-los ao servidor.
Usar políticas de cache eficientes
A próxima etapa foi garantir que não enviamos recursos duas vezes, se não for necessário.
A auditoria Política de cache ineficiente no Lighthouse nos ajudou a perceber que poderíamos otimizar nossas estratégias de armazenamento em cache para conseguir exatamente isso. Ao definir um cabeçalho de expiração max-age no nosso servidor, garantimos que, em uma visita repetida, o usuário pudesse reutilizar os recursos que ele havia feito o download antes.
O ideal é armazenar em cache o maior número possível de recursos com a maior segurança possível pelo maior período possível e fornecer tokens de validação para a revalidação eficiente dos recursos que foram atualizados.
Remover código não utilizado
Até agora, removemos as partes óbvias do download desnecessário, mas e as partes menos óbvias? Por exemplo, código não usado.
![Cobertura de código no DevTools](https://web.dev/static/articles/web-performance-made-easy/image/code-coverage-devtools-d9d9ad4c8416d.png?hl=pt-br)
Às vezes, incluímos código nos apps que não é realmente necessário. Isso acontece principalmente se você trabalhar no app por um período mais longo, se a equipe ou as dependências mudarem e, às vezes, se uma biblioteca órfã for deixada de lado. Foi exatamente isso que aconteceu com a gente.
No início, usamos a biblioteca Material Components para criar protótipos do app rapidamente. Com o tempo, passamos a usar uma aparência e uma sensação mais personalizadas e nos esquecemos completamente dessa biblioteca. Felizmente, a verificação de cobertura de código nos ajudou a encontrá-lo no nosso pacote.
É possível verificar as estatísticas de cobertura de código no DevTools, tanto para o tempo de execução quanto para o tempo de carregamento do aplicativo. Você pode ver as duas grandes listras vermelhas na captura de tela abaixo. Mais de 95% do CSS e um grande número de JavaScript não foram usados.
O Lighthouse também detectou esse problema na auditoria de regras CSS não usadas. Ele mostrou um possível poupança de mais de 400 KB. Então, voltamos ao nosso código e removemos a parte do JavaScript e do CSS dessa biblioteca.
![Se você remover o adaptador MVC, os estilos serão reduzidos para 10 KB](https://web.dev/static/articles/web-performance-made-easy/image/if-drop-mvc-adapter-sty-f311da23542ff.png?hl=pt-br)
Isso reduziu nosso pacote CSS em 20 vezes, o que é muito bom para uma confirmação pequena de duas linhas.
Isso fez com que nossa pontuação de desempenho aumentasse, e o tempo de interação melhorou muito.
No entanto, com mudanças como essa, não basta verificar as métricas e as pontuações. A remoção do código real nunca é isenta de riscos. Por isso, é importante sempre ficar atento a possíveis regressões.
Nosso código não foi usado em 95%. Ainda há 5% em algum lugar. Aparentemente, um dos nossos componentes ainda usava os estilos dessa biblioteca, as pequenas setas no controle deslizante de rabiscos. Como era muito pequeno, poderíamos incorporar manualmente esses estilos de volta aos botões.
![Os botões foram quebrados por falta de biblioteca](https://web.dev/static/articles/web-performance-made-easy/image/buttons-got-broken-missi-6e2d05b1a4f04.png?hl=pt-br)
Portanto, se você remover o código, verifique se tem um fluxo de trabalho de teste adequado para se proteger contra possíveis regressões visuais.
Evite payloads de rede muito grandes
Sabemos que recursos grandes podem deixar o carregamento da página mais lento. Elas podem custar dinheiro aos nossos usuários e ter um grande impacto nos planos de dados. Por isso, é muito importante estar atento a isso.
O Lighthouse detectou que tínhamos um problema com alguns dos nossos payloads de rede usando a auditoria Payload de rede enorme.
![Detectar payloads de rede enormes](https://web.dev/static/articles/web-performance-made-easy/image/detect-enormous-network-p-b417c0f85336d.png?hl=pt-br)
Aqui, notamos que tínhamos mais de 3 MB de código sendo enviado, o que é bastante, especialmente em dispositivos móveis.
No topo da lista, o Lighthouse destacou que tínhamos um pacote de fornecedor JavaScript de 2 MB de código não compactado. Esse também é um problema destacado pelo webpack.
Como diz o ditado: a solicitação mais rápida é a que não é feita.
O ideal é medir o valor de cada recurso que você está enviando para os usuários, avaliar o desempenho deles e decidir se vale a pena enviá-los com a experiência inicial. Porque às vezes esses recursos podem ser adiados, carregados de forma lenta ou processados durante o tempo de inatividade.
No nosso caso, como lidamos com muitos pacotes JavaScript, tivemos sorte porque a comunidade JavaScript tem um conjunto rico de ferramentas de auditoria de pacotes JavaScript.
![Auditoria de pacotes do JavaScript](https://web.dev/static/articles/web-performance-made-easy/image/javascript-bundle-auditin-bb72c40c2152f.png?hl=pt-br)
Começamos com o analisador de pacotes do webpack, que nos informou que estávamos incluindo uma dependência chamada unicode, que era de 1,6 MB de JavaScript analisado, ou seja, bastante.
Em seguida, acessamos o editor e, usando o Import Cost Plugin for Visual code, visualizamos o custo de cada módulo que estávamos importando. Isso nos permitiu descobrir qual componente estava incluindo o código que referenciava esse módulo.
Depois, mudamos para outra ferramenta, a BundlePhobia. Essa é uma ferramenta que permite inserir o nome de qualquer pacote do NPM e conferir o tamanho estimado do arquivo minificado e compactado. Encontramos uma boa alternativa para o módulo de slug que estávamos usando que pesava apenas 2, 2 KB.
Isso afetou muito nosso desempenho. Entre essa mudança e a descoberta de outras oportunidades para reduzir o tamanho do pacote de JavaScript, economizamos 2,1 MB de código.
Observamos uma melhoria de 65% no geral, considerando o tamanho compactado e minimizado desses pacotes. E descobrimos que valeu a pena fazer isso como um processo.
Em geral, tente eliminar downloads desnecessários nos seus sites e apps. Fazer um inventário dos seus recursos e medir o impacto deles na performance pode fazer uma grande diferença. Portanto, audite seus recursos com frequência.
Diminua o tempo de inicialização do JavaScript com a divisão de código
Embora payloads de rede grandes possam ter um grande impacto no app, há outra coisa que pode ter um impacto muito grande, que é o JavaScript.
O JavaScript é o recurso mais caro. Em dispositivos móveis, se você estiver enviando grandes pacotes de JavaScript, isso pode atrasar o tempo que os usuários conseguem interagir com os componentes da interface do usuário. Isso significa que eles podem tocar na interface sem que nada significativo aconteça. Por isso, é importante entender por que o JavaScript custa tanto.
É assim que um navegador processa JavaScript.
![Processamento de JavaScript](https://web.dev/static/articles/web-performance-made-easy/image/javascript-processing-a88df8122641b.png?hl=pt-br)
Primeiro, precisamos fazer o download do script. Temos um mecanismo JavaScript que precisa analisar esse código, além de compilá-lo e executá-lo.
Essas fases não levam muito tempo em um dispositivo de última geração, como um computador desktop ou um laptop, talvez até mesmo um smartphone de última geração. Mas em um smartphone mediano, esse processo pode levar de cinco a dez vezes mais tempo. Isso é o que atrasa a interatividade. Por isso, é importante tentar reduzir isso.
Para ajudar você a descobrir esses problemas com seu app, lançamos uma nova auditoria de tempo de inicialização do JavaScript no Lighthouse.
![Tempo de inicialização do JavaScript](https://web.dev/static/articles/web-performance-made-easy/image/javascript-boot-time-d9ae37a556e82.png?hl=pt-br)
No caso do app Oodle, ele informou que gastamos 1,8 segundo na inicialização do JavaScript. O que estava acontecendo era que estávamos importando de forma estática todas as nossas rotas e componentes em um pacote JavaScript monolítico.
Uma técnica para contornar isso é usar a divisão de código.
![A divisão de código é como pizza](https://web.dev/static/articles/web-performance-made-easy/image/code-splitting-is-pizza-6008484e57adc.png?hl=pt-br)
O conceito de divisão de código é o seguinte: em vez de fornecer aos usuários uma pizza inteira de JavaScript, por que não fornecer apenas uma fatia de cada vez, conforme a necessidade?
A divisão de código pode ser aplicada no nível de uma rota ou de um componente. Ele funciona muito bem com React e React Loadable, Vue.js, Angular, Polymer, Preact e várias outras bibliotecas.
Incorporamos a divisão de código ao nosso aplicativo, mudamos de importações estáticas para importações dinâmicas, permitindo que carregássemos o código de forma assíncrona conforme necessário.
![Divisão de código com importações dinâmicas](https://web.dev/static/articles/web-performance-made-easy/image/code-splitting-dynamic-i-bef50644cc8ac.png?hl=pt-br)
O impacto disso foi reduzir o tamanho dos nossos pacotes e também diminuir o tempo de inicialização do JavaScript. O tempo caiu para 0,78 segundos, tornando o app 56% mais rápido.
Em geral, se você estiver criando uma experiência com muito JavaScript, envie apenas o código necessário para o usuário.
Aproveite conceitos como divisão de código, explore ideias como o desligamento de árvore e confira o repo webpack-libs-optimizations para algumas ideias sobre como reduzir o tamanho da biblioteca se você estiver usando o webpack.
Otimizar imagens
![Piada sobre a performance de carregamento de imagens](https://web.dev/static/articles/web-performance-made-easy/image/image-loading-performance-82f3792c437f6.png?hl=pt-br)
No app Oodle, usamos muitas imagens. Infelizmente, o Lighthouse estava muito menos entusiasmado com isso do que nós. Na verdade, não conseguimos concluir as três auditorias relacionadas a imagens.
Esquecemos de otimizar nossas imagens, não estávamos dimensionando corretamente e também conseguimos alguns benefícios usando outros formatos de imagem.
![Auditorias de imagem](https://web.dev/static/articles/web-performance-made-easy/image/image-audits-719c8447f8aaf.png?hl=pt-br)
Começamos otimizando nossas imagens.
Para uma rodada de otimização única, use ferramentas visuais como ImageOptim ou XNConvert.
Uma abordagem mais automatizada é adicionar uma etapa de otimização de imagem ao processo de build com bibliotecas como imagemin.
Assim, as imagens adicionadas no futuro serão otimizadas automaticamente. Alguns CDNs, por exemplo, o Akamai ou soluções de terceiros, como o Cloudinary, o Fastly ou o Uploadcare, oferecem soluções abrangentes de otimização de imagens. Assim, você pode hospedar suas imagens nesses serviços.
Se você não quiser fazer isso devido ao custo ou a problemas de latência, projetos como Thumbor ou Imageflow oferecem alternativas auto-hospedas.
![Antes e depois da otimização](https://web.dev/static/articles/web-performance-made-easy/image/before-after-optimizatio-45b3bbf20acca.png?hl=pt-br)
Nosso PNG de plano de fundo foi sinalizado no webpack como grande, e com razão. Depois de dimensioná-lo corretamente para a janela de visualização e executá-lo no ImageOptim, reduzimos para 100 KB, o que é aceitável.
Repetir isso para várias imagens no nosso site nos permitiu reduzir significativamente o peso geral da página.
Use o formato certo para conteúdo animado
Os GIFs podem ficar muito caros. Surpreendentemente, o formato GIF nunca foi destinado a ser uma plataforma de animação. Portanto, mudar para um formato de vídeo mais adequado oferece grandes economias em termos de tamanho do arquivo.
No app Oodle, usamos um GIF como uma sequência de introdução na página inicial. De acordo com o Lighthouse, poderíamos economizar mais de 7 MB ao mudar para um formato de vídeo mais eficiente. Nosso clipe pesava cerca de 7,3 MB, muito para qualquer site razoável.Por isso, transformamos o clipe em um elemento de vídeo com dois arquivos de origem: um mp4 e um WebM para oferecer suporte a mais navegadores.
![Substituir GIFs animados por vídeo](https://web.dev/static/articles/web-performance-made-easy/image/replace-animated-gifs-vi-fc084e0a3fb4e.png?hl=pt-br)
Usamos a ferramenta FFmpeg para converter o GIF de animação no arquivo mp4. O formato WebM oferece economias ainda maiores. A API ImageOptim pode fazer essa conversão para você.
ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4
Conseguimos economizar mais de 80% do nosso peso total graças a essa conversão. Isso reduziu para cerca de 1 MB.
Ainda assim, 1 MB é um recurso grande para enviar, especialmente para um usuário com uma largura de banda restringida. Felizmente, podemos usar a API Effective Type para saber se a largura de banda está lenta e fornecer um JPEG muito menor.
Essa interface usa o tempo de ida e volta efetivo e os valores de redução para estimar o tipo de rede que o usuário está usando. Ele simplesmente retorna uma string, 2G lento, 2G, 3G ou 4G. Portanto, dependendo desse valor, se o usuário estiver abaixo de 4G, poderíamos substituir o elemento de vídeo pela imagem.
if (navigator.connection.effectiveType) { ... }
Isso reduz um pouco a experiência, mas pelo menos o site pode ser usado em uma conexão lenta.
Carregamento lento de imagens fora da tela
Carrosséis, controles deslizantes ou páginas muito longas geralmente carregam imagens, mesmo que o usuário não consiga vê-las na página imediatamente.
O Lighthouse sinaliza esse comportamento na auditoria de imagens fora da tela, e você também pode conferir no painel de rede do DevTools. Se você notar que há muitas imagens chegando enquanto apenas algumas estão visíveis na página, talvez seja melhor usar o carregamento lento.
O carregamento lento ainda não tem suporte nativo no navegador. Por isso, precisamos usar o JavaScript para adicionar esse recurso. Usamos a biblioteca Lazysizes para adicionar o comportamento de carregamento lento às nossas capas do Oodle.
<!-- Import library -->
import lazysizes from 'lazysizes' <!-- or -->
<script src="lazysizes.min.js"></script>
<!-- Use it -->
<img data-src="image.jpg" class="lazyload"/>
<img class="lazyload"
data-sizes="auto"
data-src="image2.jpg"
data-srcset="image1.jpg 300w,
image2.jpg 600w,
image3.jpg 900w"/>
O Lazysizes é inteligente porque não apenas rastreia as mudanças de visibilidade do elemento, mas
também faz a pré-busca proativa de elementos que estão próximos da visualização para uma experiência ideal do usuário.
Ele também oferece uma integração opcional do IntersectionObserver
, que oferece pesquisas de visibilidade muito
eficientes.
Depois dessa mudança, nossas imagens estão sendo buscadas sob demanda. Se você quiser se aprofundar nesse assunto, confira o images.guide, um recurso muito útil e abrangente.
Ajude o navegador a entregar recursos essenciais com antecedência
Nem todos os bytes enviados para o navegador têm o mesmo grau de importância, e o navegador sabe disso. Muitos navegadores têm heurísticas para decidir o que precisam buscar primeiro. Por isso, às vezes, eles vão buscar CSS antes de imagens ou scripts.
Algo que pode ser útil é informarmos, como autores da página, ao navegador o que é
realmente importante para nós. Felizmente, nos últimos anos, os fornecedores de navegadores têm
adicionado vários recursos para ajudar com isso, como
dicas de recursos, como link rel=preconnect
,
preload
ou prefetch
.
Esses recursos que foram trazidos para a plataforma da Web ajudam o navegador a buscar a coisa certa no momento certo e podem ser um pouco mais eficientes do que algumas das abordagens de carregamento personalizado com base na lógica que são feitas usando script.
Vamos conferir como o Lighthouse nos orienta a usar alguns desses recursos de forma eficaz.
A primeira coisa que o Lighthouse nos diz para fazer é evitar várias viagens de ida e volta caras para qualquer origem.
![Evite viagens de ida e volta caras para qualquer origem](https://web.dev/static/articles/web-performance-made-easy/image/avoid-multiple-costly-ro-1349e14da4d4d.png?hl=pt-br)
No caso do app Oodle, usamos muito as fontes do Google. Sempre que você soltar uma folha de estilo de fonte do Google na página, ela será conectada a dois subdomínios. O Lighthouse está dizendo que, se conseguirmos aquecer essa conexão, poderemos economizar até 300 milissegundos no tempo de conexão inicial.
Usando a pré-conexão de link rel, podemos mascarar essa latência de conexão.
Isso pode ter um grande impacto, especialmente em algo como as fontes do Google, em que o CSS da fonte é hospedado em googleapis.com e os recursos de fonte são hospedados em Gstatic. Aplicamos essa otimização e reduzimos algumas centenas de milissegundos.
A próxima coisa que o Lighthouse sugere é pré-carregar solicitações importantes.
![Pré-carregar solicitações de chave](https://web.dev/static/articles/web-performance-made-easy/image/preload-key-requests-a2751a962b7e2.png?hl=pt-br)
O <link rel=preload>
é muito poderoso. Ele informa ao navegador que um recurso é necessário como
parte da navegação atual e tenta fazer com que o navegador o busque o mais rápido possível.
Aqui, o Lighthouse está dizendo que precisamos pré-carregar nossos principais recursos de fonte da Web, porque estamos carregando duas fontes da Web.
O pré-carregamento em uma fonte da Web é assim: especificando rel=preload
, você transmite as
com
o tipo de fonte e, em seguida, especifica o tipo de fonte que você está tentando carregar, como woff2.
O impacto disso na sua página é bastante forte.
![Impacto do pré-carregamento de recursos](https://web.dev/static/articles/web-performance-made-easy/image/impact-preloading-resour-d6cf8908f75e3.png?hl=pt-br)
Normalmente, sem usar o pré-carregamento de link rel, se as fontes da Web forem essenciais para a página, o que o navegador precisa fazer é, em primeiro lugar, buscar o HTML, analisar o CSS e, mais tarde, buscar as fontes da Web.
Usando o pré-carregamento de link rel, assim que o navegador analisar seu HTML, ele poderá começar a buscar essas fontes da Web muito mais cedo. No caso do nosso app, isso reduziu um segundo do tempo que levava para renderizar texto usando nossas fontes da Web.
Não é tão simples tentar carregar fontes com o Google Fonts. Há um problema.
Os URLs de fontes do Google que especificamos nas nossas fontes nas folhas de estilo são atualizados com frequência pela equipe de fontes. Esses URLs podem expirar ou ser atualizados com frequência. Portanto, se você quiser ter controle total sobre a experiência de carregamento de fontes, sugerimos que você hospede as fontes da Web por conta própria. Isso pode ser ótimo porque dá acesso a recursos como o pré-carregamento de rel de link.
No nosso caso, a ferramenta Google Web Fonts Helper foi muito útil para nos ajudar a desativar algumas dessas fontes da Web e configurá-las localmente. Confira essa ferramenta.
Se você estiver usando fontes da Web como parte dos recursos essenciais ou se for JavaScript, tente ajudar o navegador a entregar os recursos essenciais o mais rápido possível.
Experimental: dicas de prioridade
Temos algo especial para compartilhar com você hoje. Além de recursos como dicas de recursos e pré-carregamento, estamos trabalhando em um novo recurso experimental do navegador chamado dicas de prioridade.
![Definir a prioridade do conteúdo visível inicialmente](https://web.dev/static/articles/web-performance-made-easy/image/set-priority-the-initial-a002f3faeabf3.png?hl=pt-br)
Esse é um novo recurso que permite indicar ao navegador a importância de um recurso. Ele expõe um novo atributo, "importance", com os valores "low", "high" ou "auto".
Isso nos permite transmitir a redução da prioridade de recursos menos importantes, como estilos, imagens ou chamadas de API de busca não essenciais para reduzir a contenção. Também podemos aumentar a prioridade de coisas mais importantes, como nossas imagens principais.
No caso do nosso app Oodle, isso levou a um lugar prático em que pudemos otimizar.
![Definir a prioridade do conteúdo visível inicialmente](https://web.dev/static/articles/web-performance-made-easy/image/set-priority-the-initial-b31819a78b75c.png?hl=pt-br)
Antes de adicionar o carregamento lento às imagens, o navegador abria um carrossel com todos os doodles e buscava todas as imagens no início do carrossel com alta prioridade. Infelizmente, as imagens no meio do carrossel eram as mais importantes para o usuário. Então, definimos a importância dessas imagens de plano de fundo como muito baixa, as de primeiro plano como muito alta, e isso teve um impacto de dois segundos em relação ao 3G lento e a rapidez com que conseguimos buscar e renderizar essas imagens. Uma experiência positiva.
Esperamos lançar esse recurso na versão Canary em algumas semanas. Fique de olho.
Tenha uma estratégia de carregamento de fontes da Web
A tipografia é fundamental para um bom design. Se você estiver usando fontes da Web, não bloqueie a renderização do texto e não mostre texto invisível.
Agora, destacamos isso no Lighthouse com a auditoria evitar texto invisível enquanto as fontes da Web estão sendo carregadas.
![Evite texto invisível enquanto as fontes da Web estão sendo carregadas](https://web.dev/static/articles/web-performance-made-easy/image/avoid-invisible-text-whil-d461292533245.png?hl=pt-br)
Se você carregar as fontes da Web usando um bloco de fonte, o navegador vai decidir o que fazer se a busca da fonte da Web demorar muito. Alguns navegadores vão esperar até três segundos para isso antes de retornar a uma fonte do sistema e, eventualmente, trocar por ela depois que for feita o download.
Estamos tentando evitar esse texto invisível. Nesse caso, não seria possível ver os
doodles clássicos da semana se a fonte da Web demorasse muito. Felizmente, com um novo recurso chamado
font-display
, você tem muito mais controle sobre esse processo.
@font-face {
font-family: 'Montserrat';
font-style: normal;
font-display: swap;
font-weight: 400;
src: local('Montserrat Regular'), local('Montserrat-Regular'),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url('montserrat-v12-latin-regular.woff2') format('woff2'),
/* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
url('montserrat-v12-latin-regular.woff') format('woff');
}
A exibição de fontes ajuda a decidir como as fontes da Web serão renderizadas ou substituídas com base no tempo necessário para a troca.
Neste caso, estamos usando a troca de exibição de fontes. A troca dá à fonte um período de bloqueio de zero segundo e um período de troca infinito. Isso significa que o navegador vai exibir o texto imediatamente com uma fonte de fallback se ela demorar para carregar. E ele vai ser trocado quando a fonte estiver disponível.
No caso do nosso app, isso foi ótimo porque nos permitiu mostrar um texto significativo logo no início e fazer a transição para a fonte da Web quando ela estivesse pronta.
![Resultado da exibição da fonte](https://web.dev/static/articles/web-performance-made-easy/image/font-display-outcome-a014081404b38.png?hl=pt-br)
Em geral, se você estiver usando fontes da Web, como uma grande porcentagem da Web, tenha uma boa estratégia de carregamento de fontes da Web.
Há muitos recursos da plataforma da Web que você pode usar para otimizar a experiência de carregamento de fontes, mas confira também o repo Web Font Recipes do Zach Leatherman, porque ele é muito bom.
Reduzir scripts que bloqueiam a renderização
Há outras partes do nosso aplicativo que poderíamos enviar mais cedo na cadeia de download para oferecer pelo menos uma experiência básica do usuário um pouco mais cedo.
Na faixa de linha do tempo do Lighthouse, é possível ver que, durante os primeiros segundos em que todos os recursos estão sendo carregados, o usuário não consegue acessar nenhum conteúdo.
![Reduzir a oportunidade de folhas de estilo que bloqueiam a renderização](https://web.dev/static/articles/web-performance-made-easy/image/reduce-render-blocking-st-ee605dfe41336.png?hl=pt-br)
O download e o processamento de folhas de estilo externas estão impedindo o processo de renderização de fazer qualquer progresso.
Podemos tentar otimizar nosso caminho de renderização crítico entregando alguns dos estilos um pouco mais cedo.
Se extrairmos os estilos responsáveis por essa renderização inicial e os colocarmos inline no HTML, o navegador poderá renderizá-los imediatamente sem esperar que as folhas de estilo externas cheguem.
No nosso caso, usamos um módulo NPM chamado Critical para incorporar nosso conteúdo crítico em index.html durante uma etapa de build.
Embora esse módulo tenha feito a maior parte do trabalho pesado para nós, ainda era um pouco complicado fazer isso funcionar bem em diferentes rotas.
Se você não tiver cuidado ou se a estrutura do site for muito complexa, pode ser muito difícil introduzir esse tipo de padrão se você não tiver planejado a arquitetura de shell do app desde o início.
Por isso, é tão importante considerar a performance desde o início. Se você não projetar para performance desde o início, é provável que encontre problemas mais tarde.
No final, nosso risco valeu a pena, conseguimos fazer o app funcionar e ele começou a entregar conteúdo muito mais cedo, melhorando significativamente o primeiro tempo de pintura significativo.
O resultado
Essa foi uma longa lista de otimizações de desempenho que aplicamos ao nosso site. Vamos analisar o resultado. Confira como nosso app foi carregado em um dispositivo móvel médio em uma rede 3G, antes e depois da otimização.
A pontuação de desempenho do Lighthouse aumentou de 23 para 91. Esse é um progresso muito bom em termos de velocidade. Todas as mudanças foram impulsionadas por nós verificando e seguindo continuamente o relatório do Lighthouse. Se você quiser conferir como implementamos tecnicamente todas as melhorias, confira nosso repositório, especialmente as PRs que foram enviadas para ele.
Performance preditiva: experiências do usuário orientadas por dados
Acreditamos que o aprendizado de máquina representa uma oportunidade incrível para o futuro em muitas áreas. Uma ideia que esperamos que incentive mais experimentos no futuro é que dados reais podem orientar as experiências do usuário que estamos criando.
Hoje, tomamos muitas decisões arbitrárias sobre o que o usuário pode querer ou precisar e, portanto, o que vale a pena ser pré-buscado, pré-carregado ou pré-armazenado em cache. Se a suposição estiver correta, poderemos priorizar uma pequena quantidade de recursos, mas é muito difícil dimensioná-los para todo o site.
Temos dados disponíveis para melhorar nossas otimizações. Usando a API Google Analytics Reporting, é possível conferir a próxima página principal e as porcentagens de saída de qualquer URL no nosso site e, portanto, tirar conclusões sobre quais recursos devem ser priorizados.
Se combinarmos isso com um bom modelo de probabilidade, evitaremos o desperdício de dados do usuário com a precarga excessiva de conteúdo. Podemos aproveitar esses dados do Google Analytics e usar aprendizado de máquina e modelos como cadeias de Markov ou redes neurais para implementar esses modelos.
![Agrupamento orientado a dados para apps da Web](https://web.dev/static/articles/web-performance-made-easy/image/data-driven-bundling-web-3843c496c6e42.png?hl=pt-br)
Para facilitar esses experimentos, anunciamos uma nova iniciativa chamada Guess.js.
![Guess.js](https://web.dev/static/articles/web-performance-made-easy/image/guessjs-8f7d906237584.png?hl=pt-br)
O Guess.js é um projeto focado em experiências do usuário baseadas em dados para a Web. Esperamos que ele inspire a exploração do uso de dados para melhorar o desempenho da Web e ir além. Tudo é de código aberto e está disponível no GitHub. Ele foi criado em colaboração com a comunidade de código aberto por Minko Gechev, Kyle Matthews do Gatsby, Katie Hempenius e vários outros.
Confira o Guess.js e nos conte o que você achou.
Resumo
As pontuações e métricas ajudam a melhorar a velocidade da Web, mas são apenas meios, não as metas em si.
Todos nós já tivemos problemas com carregamento lento de páginas em trânsito, mas agora temos a oportunidade de oferecer aos nossos usuários experiências mais agradáveis que carregam muito rápido.
Melhorar a performance é uma jornada. Muitas pequenas mudanças podem gerar grandes ganhos. Ao usar as ferramentas de otimização certas e ficar de olho nos relatórios do Lighthouse, você pode oferecer uma experiência melhor e mais inclusiva aos usuários.
Agradecemos especialmente a Ward Peeters, Minko Gechev, Kyle Mathews, Katie Hempenius, Dom Farolino, Yoav Weiss, Susie Lu, Yusuke Utsunomiya, Tom Ankers, Lighthouse e Google Doodles.