Otimizar o carregamento e a renderização de WebFont

Uma WebFont "completa" que inclui todas as variantes estilísticas, que você talvez não precise, além de todos os glifos, que podem não ser usados, pode resultar facilmente em um download de vários megabytes. Neste post, você vai descobrir como otimizar o carregamento de WebFonts para que os visitantes façam o download apenas do que vão usar.

Para resolver o problema de arquivos grandes que contêm todas as variantes, a regra CSS @font-face foi projetada especificamente para permitir que você divida a família de fontes em uma coleção de recursos. Por exemplo, subconjuntos de Unicode e variantes de estilo distintas.

Com essas declarações, o navegador descobre os subconjuntos e as variantes necessários e faz o download do conjunto mínimo necessário para renderizar o texto, o que é muito conveniente. No entanto, se você não tomar cuidado, isso também pode criar um gargalo de desempenho no caminho de renderização crítico e atrasar a renderização de texto.

O comportamento padrão

O carregamento lento de fontes tem uma implicação oculta importante que pode atrasar a renderização de texto. O navegador precisa criar a árvore de renderização, que depende das árvores DOM e CSSOM, antes de saber quais recursos de fonte são necessários para renderizar o texto. Como resultado, as solicitações de fontes são adiadas bem depois de outros recursos críticos, e o navegador pode ser bloqueado para renderizar texto até que o recurso seja buscado.

Caminho crítico de renderização da fonte

  1. O navegador solicita o documento HTML.
  2. O navegador começa a analisar a resposta HTML e a construir o DOM.
  3. O navegador descobre CSS, JS e outros recursos e envia solicitações.
  4. O navegador constrói o CSSOM depois que todo o conteúdo do CSS é recebido e o combina com a árvore DOM para construir a árvore de renderização.
    • As solicitações de fonte são enviadas depois que a árvore de renderização indica quais variantes de fonte são necessárias para renderizar o texto especificado na página.
  5. O navegador executa o layout e pinta o conteúdo na tela.
    • Se a fonte ainda não estiver disponível, o navegador poderá não renderizar os pixels de texto.
    • Depois que a fonte fica disponível, o navegador pinta os pixels de texto.

A "corrida" entre a primeira pintura do conteúdo da página, que pode ser feita logo após a criação da árvore de renderização, e a solicitação do recurso de fonte é o que cria o "problema de texto em branco", em que o navegador pode renderizar o layout da página, mas omite qualquer texto.

Ao carregar previamente as WebFonts e usar font-display para controlar como os navegadores se comportam com fontes indisponíveis, é possível evitar páginas em branco e mudanças de layout devido ao carregamento de fontes.

Pré-carregar recursos da WebFont

Se houver uma alta probabilidade de que sua página precise de uma WebFont específica hospedada em um URL que você conhece com antecedência, aproveite a priorização de recursos. O uso de <link rel="preload"> vai acionar uma solicitação para a WebFont no início do caminho de renderização crítico, sem precisar esperar a criação do CSSOM.

Personalizar o atraso de renderização de texto

Embora o pré-carregamento aumente a probabilidade de uma WebFont estar disponível quando o conteúdo de uma página for renderizado, ele não oferece garantias. Você ainda precisa considerar como os navegadores se comportam ao renderizar texto que usa um font-family que ainda não está disponível.

Na postagem Evitar texto invisível durante o carregamento de fontes, você pode conferir que o comportamento padrão do navegador não é consistente. No entanto, é possível informar aos navegadores modernos como você quer que eles se comportem usando font-display.

Browser Support

  • Chrome: 60.
  • Edge: 79.
  • Firefox: 58.
  • Safari: 11.1.

Source

Assim como os comportamentos de tempo limite de fontes implementados por alguns navegadores, font-display segmenta a vida útil de um download de fonte em três períodos principais:

  1. O primeiro período é o período de bloco de fonte. Durante esse período, se a família de fontes não for carregada, qualquer elemento que tente usá-la terá que renderizar com uma família de fontes substituta invisível. Se o tipo de fonte for carregado durante o período de bloqueio, ele será usado normalmente.
  2. O período de troca de fonte ocorre imediatamente após o período de bloqueio de fonte. Durante esse período, se a família de fontes não for carregada, qualquer elemento que tente usá-la precisará renderizar com uma família de fontes substituta. Se o tipo de fonte for carregado durante o período de troca, ele será usado normalmente.
  3. O período de falha da fonte ocorre imediatamente após o período de troca de fonte. Se o tipo de fonte ainda não estiver carregado quando esse período começar, ele será marcado como uma carga com falha, causando a substituição de fonte normal. Caso contrário, o tipo de fonte será usado normalmente.

Com a compreensão desses períodos, é possível usar font-display para decidir como a fonte será renderizada, dependendo de quando ou se ela foi transferida por download.

Para trabalhar com a propriedade font-display, adicione-a às regras @font-face:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  font-display: auto; /* or block, swap, fallback, optional */
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2'), /* will be preloaded */
       url('/fonts/awesome-l.woff') format('woff'),
       url('/fonts/awesome-l.ttf') format('truetype'),
       url('/fonts/awesome-l.eot') format('embedded-opentype');
  unicode-range: U+000-5FF; /* Latin glyphs */
}

No momento, font-display aceita os seguintes valores:

  • auto
  • block
  • swap
  • fallback
  • optional

Para mais informações sobre o pré-carregamento de fontes e a propriedade font-display, consulte as seguintes postagens:

A API Font Loading

Usados juntos, <link rel="preload"> e o CSS font-display oferecem muito controle sobre o carregamento e a renderização de fontes, sem adicionar muita sobrecarga. No entanto, se você precisar de mais personalizações e quiser incorrer na sobrecarga introduzida pela execução do JavaScript, há outra opção.

A API Font Loading fornece uma interface de script para definir e manipular faces de fontes CSS, rastrear o progresso do download e substituir o comportamento padrão de carregamento lento. Por exemplo, se você tiver certeza de que uma variante de fonte específica é necessária, defina-a e informe ao navegador para iniciar uma busca imediata do recurso de fonte:

Browser Support

  • Chrome: 35.
  • Edge: 79.
  • Firefox: 41.
  • Safari: 10.

Source

var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {
  style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});

// don't wait for the render tree, initiate an immediate fetch!
font.load().then(function() {
  // apply the font (which may re-render text and cause a page reflow)
  // after the font has finished downloading
  document.fonts.add(font);
  document.body.style.fontFamily = "Awesome Font, serif";

  // OR... by default the content is hidden,
  // and it's rendered after the font is available
  var content = document.getElementById("content");
  content.style.visibility = "visible";

  // OR... apply your own render strategy here...
});

Além disso, como é possível verificar o status da fonte (pelo método check()) e acompanhar o progresso do download, também é possível definir uma estratégia personalizada para renderizar texto nas páginas:

  • É possível pausar toda a renderização de texto até que a fonte esteja disponível.
  • É possível implementar um tempo limite personalizado para cada fonte.
  • É possível usar a fonte de fallback para desbloquear a renderização e injetar um novo estilo que use a fonte desejada depois que ela estiver disponível.

O melhor de tudo é que você também pode misturar as estratégias acima para diferentes conteúdos na página. Por exemplo, é possível atrasar a renderização de texto em algumas seções até que a fonte esteja disponível, usar uma fonte substituta e renderizar novamente após o término do download da fonte.

O armazenamento em cache adequado é essencial

Os recursos de fonte geralmente são estáticos e não recebem atualizações frequentes. Como resultado, elas são ideais para um prazo de validade máximo longo. Especifique um cabeçalho ETag condicional e uma política Cache-Control ideal para todos os recursos de fonte.

Se o aplicativo da Web usar um service worker, a veiculação de recursos de fonte com uma estratégia de cache primeiro é adequada para a maioria dos casos de uso.

Não armazene fontes usando localStorage ou IndexedDB. Cada um deles tem seu próprio conjunto de problemas de desempenho. O cache HTTP do navegador oferece o mecanismo mais eficiente e robusto para fornecer recursos de fonte ao navegador.

Lista de verificação de carregamento de Web Fonts

  • Personalize o carregamento e a renderização de fontes usando <link rel="preload">, font-display ou a API Font Loading:o comportamento de carregamento lento padrão pode resultar em renderização de texto atrasada. Esses recursos da plataforma da Web permitem que você substitua esse comportamento para fontes específicas e especifique renderizações personalizadas e estratégias de tempo limite para diferentes conteúdos na página.
  • Especificar políticas de revalidação e armazenamento em cache ideal:as fontes são recursos estáticos que são atualizados com pouca frequência. Verifique se os servidores fornecem um carimbo de data/hora de idade máxima de longa duração e um token de revalidação para permitir a reutilização eficiente de fontes entre páginas diferentes. Se você estiver usando um worker de serviço, uma estratégia de cache-first é adequada.

Testes automatizados para o comportamento de carregamento de WebFont com o Lighthouse

O Lighthouse pode ajudar a automatizar o processo de garantir que você está seguindo as práticas recomendadas de otimização de fontes da Web.

As auditorias a seguir podem ajudar a garantir que suas páginas continuem seguindo as práticas recomendadas de otimização de fontes da Web ao longo do tempo: