Um pacote Next.js para gerenciar bibliotecas de terceiros

Em 2021, a equipe do Chrome Aurora introduziu o componente de script para melhorar o desempenho de carregamento de scripts de terceiros no Next.js. Desde o lançamento, ampliamos os recursos para tornar o carregamento de recursos de terceiros mais fácil e rápido para os desenvolvedores.

Esta postagem do blog traz uma visão geral dos recursos mais recentes que lançamos, principalmente a biblioteca @next/third-parties, além de uma descrição das iniciativas futuras do nosso roteiro.

Implicações de desempenho de scripts de terceiros

41% de todas as solicitações de terceiros em sites do Next.js são scripts. Ao contrário de outros tipos de conteúdo, os scripts podem levar um tempo considerável para download e execução, o que pode bloquear a renderização e atrasar a interatividade do usuário. Dados do Chrome User Experience Report (CrUX, na sigla em inglês) mostram que os sites do Next.js que carregam mais scripts de terceiros têm taxas de aprovação menores de Interaction to Next Paint (INP) e Maior exibição de conteúdo (LCP, na sigla em inglês).

Gráfico de barras que mostra uma queda na porcentagem do Next.js que alcançou boas pontuações de INP e LCP em proporção ao número de terceiros carregados
Relatório CrUX de dezembro de 2023 (110.823 sites)

A correlação observada no gráfico não implica causalidade. No entanto, os experimentos locais oferecem outras evidências de que scripts de terceiros afetam significativamente o desempenho da página. Por exemplo, o gráfico abaixo compara várias métricas de laboratórios quando um contêiner do Gerenciador de tags do Google, composto por 18 tags selecionadas aleatoriamente, é adicionado à Taxonomy, um conhecido app de exemplo do Next.js.

Gráfico de barras que mostra a diferença em várias métricas do laboratório quando um site é carregado com e sem o Gerenciador de tags do Google
WebPageTest (4G para dispositivos móveis, Virgínia, EUA)

A documentação do WebPageTest fornece detalhes sobre como esses tempos são medidos. Com uma rápida olhada, está claro que todas essas métricas de laboratório são afetadas pelo contêiner do GTM. Por exemplo, o Tempo total de bloqueio (TBT, na sigla em inglês), um proxy de laboratório útil que se aproxima do INP, teve um aumento de quase 20 vezes.

Componente de script

Quando enviamos o componente <Script> para o Next.js, fizemos questão de inseri-lo com uma API fácil de usar que é bem parecida com o elemento <script> tradicional. Com ele, os desenvolvedores podem colocalizar um script de terceiros em qualquer componente do aplicativo, e o Next.js vai sequenciar o script depois que os recursos essenciais forem carregados.

<!-- By default, script will load after page becomes interactive -->
<Script src="https://example.com/sample.js" />

<!-- Script is injected server-side and fetched before any page hydration occurs -->
<Script strategy=”beforeInteractive” src="https://example.com/sample.js" />

<!-- Script is fetched later during browser idle time -->
<Script strategy=”lazyOnload” src="https://example.com/sample.js" />

Dezenas de milhares de aplicativos Next.js, incluindo sites conhecidos como Patreon, Target e Notion, usam o componente <Script>. Apesar da eficácia, alguns desenvolvedores levantaram preocupações sobre as seguintes coisas:

  • Onde colocar o componente <Script> em um app Next.js, seguindo as instruções de instalação variáveis de diferentes provedores terceirizados (experiência do desenvolvedor).
  • Qual estratégia de carregamento é a ideal para diferentes scripts de terceiros (experiência do usuário).

Para abordar essas duas preocupações, lançamos a @next/third-parties, uma biblioteca especializada que oferece um conjunto de componentes e utilitários otimizados personalizados para terceiros conhecidos.

Experiência do desenvolvedor: como simplificar o gerenciamento de bibliotecas de terceiros

Muitos scripts de terceiros são usados em uma porcentagem significativa dos sites do Next.js. O Gerenciador de tags do Google é o mais usado, com 66% dos sites, respectivamente. @next/third-parties se baseia no componente <Script> introduzindo wrappers de nível superior projetados para simplificar o uso nesses casos de uso comuns.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleTagManager gtmId="GTM-XYZ" />
    </html>
  );
}

O Google Analytics, outro script de terceiros amplamente utilizado (52% dos sites do Next.js), também tem um componente dedicado.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleAnalytics gaId="G-XYZ" />
    </html>
  );
}

@next/third-parties simplifica o processo de carregamento de scripts usados com frequência, mas também amplia nossa capacidade de desenvolver utilitários para outras categorias de terceiros, como incorporações. Por exemplo, as incorporações do Google Maps e do YouTube são usadas em 8% e 4% dos sites do Next.js, respectivamente, e também enviamos componentes para facilitar o carregamento.

import { GoogleMapsEmbed } from "@next/third-parties/google";
import { YouTubeEmbed } from "@next/third-parties/google";

export default function Page() {
  return (
    <>
      <GoogleMapsEmbed
        apiKey="XYZ"
        height={200}
        width="100%"
        mode="place"
        q="Brooklyn+Bridge,New+York,NY"
      />
      <YouTubeEmbed videoid="ogfYd705cRs" height={400} params="controls=0" />
    </>
  );
}

Experiência do usuário: como fazer com que bibliotecas de terceiros carreguem mais rápido

Em um mundo ideal, todas as bibliotecas de terceiros amplamente adotadas seriam totalmente otimizadas, o que torna desnecessárias as abstrações que melhorem o desempenho. No entanto, até que isso se torne uma realidade, podemos tentar melhorar a experiência do usuário quando fizer a integração com frameworks conhecidos, como o Next.js. Podemos testar diferentes técnicas de carregamento, garantir que os scripts sejam sequenciados da maneira correta e, por fim, compartilhar nosso feedback com provedores terceiros para incentivar mudanças upstream.

Veja as incorporações do YouTube, por exemplo. Algumas implementações alternativas têm um desempenho muito melhor do que a incorporação nativa. Atualmente, o componente <YouTubeEmbed> exportado por @next/third-parties usa o lite-youtube-embed que, quando demonstrado em uma comparação do Next.js "Hello, World", é carregado consideravelmente mais rápido.

GIF que mostra a comparação de carregamento de página entre o componente incorporado do YouTube e um iframe normal do YouTube
WebPageTest (4G para dispositivos móveis, Virgínia, EUA)

Da mesma forma, no Google Maps, incluímos loading="lazy" como um atributo padrão da incorporação para garantir que o mapa seja carregado somente quando estiver a uma determinada distância da janela de visualização. Pode parecer óbvio incluir um atributo, principalmente porque a documentação do Google Maps o inclui no snippet de código de exemplo, mas apenas 45% dos sites Next.js que incorporam o Google Maps usam loading="lazy".

Como executar scripts de terceiros em um worker da Web

Uma técnica avançada que estamos conhecendo no @next/third-parties é facilitar a descarga de scripts de terceiros em um worker da Web. Famoso por bibliotecas como o Partytown, isso pode reduzir substancialmente o impacto dos scripts de terceiros no desempenho da página, realocando-os totalmente para fora da linha de execução principal.

O GIF animado a seguir mostra as variações nas tarefas longas e no tempo de bloqueio da linha de execução principal ao aplicar diferentes estratégias de <Script> a um contêiner do GTM em um site Next.js. Embora a alternância entre opções de estratégia atrase apenas o tempo de execução desses scripts, realocá-los para um worker da Web elimina completamente o tempo desses scripts na linha de execução principal.

GIF que mostra as diferenças no tempo de bloqueio da linha de execução principal para as diferentes estratégias de script
WebPageTest (4G para dispositivos móveis, Virgínia, EUA)

Neste exemplo específico, mover a execução do contêiner do GTM e os scripts de tag associados para um web worker reduziu o TBT em 92%.

Vale ressaltar que, se não for gerenciada com cuidado, essa técnica pode corromper muitos scripts de terceiros silenciosamente, tornando a depuração desafiadora. Nos próximos meses, vamos validar se algum componente de terceiros oferecido pelo @next/third-parties funciona corretamente quando executado em um worker da Web. Nesse caso, vamos oferecer uma maneira fácil e opcional para os desenvolvedores usarem essa técnica.

Próximas etapas

No processo de desenvolvimento desse pacote, ficou evidente que havia a necessidade de centralizar as recomendações de carregamento de terceiros para que outros frameworks também pudessem se beneficiar das mesmas técnicas usadas. Isso nos levou a criar a Third Party Capital, uma biblioteca que usa JSON para descrever técnicas de carregamento de terceiros e atualmente serve como base para a @next/third-parties.

Nas próximas etapas, continuaremos nos concentrando em melhorar os componentes fornecidos para o Next.js, além de expandir nossos esforços para incluir utilitários semelhantes em outras estruturas e plataformas de CMS conhecidas. No momento, estamos em colaboração com os mantenedores da Nuxt e planejamos lançar em breve utilitários de terceiros semelhantes, personalizados para o ecossistema da empresa.

Se um dos terceiros que você usa no app Next.js tiver suporte de @next/third-parties, instale o pacote e tente. Gostaríamos de receber seu feedback sobre o GitHub.