Um pacote Next.js para gerenciar bibliotecas de terceiros

Em 2021, a equipe do Chrome Aurora introduziu o componente de script para melhorar o carregamento de scripts de terceiros no Next.js. Desde o lançamento, ampliamos os recursos para facilitar e acelerar o carregamento de recursos de terceiros para os desenvolvedores.

Esta postagem do blog oferece uma visão geral dos recursos mais recentes que lançamos, principalmente a biblioteca @next/third-parties, bem como um resumo das iniciativas futuras no nosso cronograma.

Implicações no 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 serem transferidos por download e executados, o que pode bloquear a renderização e atrasar a interação do usuário. Os 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 de Largest Contentful Paint (LCP).

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

A correlação observada neste gráfico não implica causalidade. No entanto, os experimentos locais fornecem evidências adicionais de que os scripts de terceiros afetam significativamente a performance 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 (com 18 tags selecionadas aleatoriamente) é adicionado à Taxonomia, um app de exemplo conhecido do Next.js.

Gráfico de barras que mostra a diferença em várias métricas de laboratório quando um site é carregado com e sem o Gerenciador de tags do Google
WebPageTest (dispositivo móvel 4G - Virginia, EUA)

A documentação do WebPageTest oferece detalhes sobre como esses tempos são medidos. De relance, fica claro que todas essas métricas do 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 útil do laboratório que se aproxima do INP, teve um aumento de quase 20 vezes.

Componente de script

Quando lançamos o componente <Script> no Next.js, nos certificamos de apresentá-lo por meio de uma API fácil de usar que se assemelha muito ao elemento <script> tradicional. Com ele, os desenvolvedores podem colocalizar um script de terceiros em qualquer componente do aplicativo, e o Next.js faz o sequenciamento do 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 expressaram preocupações sobre os seguintes assuntos:

  • Onde colocar o componente <Script> em um app Next.js respeitando as diferentes instruções de instalação 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 lidar com 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 facilitar o gerenciamento de bibliotecas de terceiros

Muitos scripts de terceiros são usados em uma porcentagem significativa de sites Next.js, sendo o Gerenciador de tags do Google o mais popular, usado por 66% dos sites, respectivamente. O @next/third-parties é criado com base 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 usado (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. Também lançamos 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 as bibliotecas de terceiros carreguem mais rápido

Em um mundo perfeito, todas as bibliotecas de terceiros amplamente adotadas seriam totalmente otimizadas, tornando desnecessárias as abstrações que melhoram o desempenho delas. No entanto, até que isso se torne realidade, podemos tentar melhorar a experiência do usuário quando integrada a 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 externos para incentivar mudanças upstream.

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

GIF que mostra a comparação do carregamento da página entre o componente de incorporação do YouTube e um iframe normal do YouTube
WebPageTest (Mobile 4G - Virginia EUA)

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

Como executar scripts de terceiros em um worker da Web

Uma técnica avançada que estamos explorando em @next/third-parties é facilitar o descarregamento de scripts de terceiros para um web worker. Popularizado por bibliotecas como Partytown, isso pode reduzir significativamente o impacto dos scripts de terceiros na performance da página, relocando-os totalmente 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 <Script> a um contêiner do GTM em um site do Next.js. Embora a troca entre as opções de estratégia apenas atrase o momento em que esses scripts são executados, a mudança para um worker da Web elimina completamente o tempo deles na linha de execução principal.

GIF que mostra diferenças no tempo de bloqueio da linha de execução principal para as diferentes estratégias do script
WebPageTest (Mobile 4G - Virginia EUA)

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

É importante observar que, se não for gerenciada com cuidado, essa técnica pode interromper silenciosamente muitos scripts de terceiros, o que dificulta a depuração. Nos próximos meses, vamos validar se os componentes de terceiros oferecidos pelo @next/third-parties funcionam corretamente quando executados em um worker da Web. Em caso afirmativo, vamos trabalhar para 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 subjacentes usadas. Isso nos levou a criar o Third Party Capital, uma biblioteca que usa JSON para descrever técnicas de carregamento de terceiros, que atualmente servem como base para @next/third-parties.

Nas próximas etapas, vamos continuar nos concentrando em melhorar os componentes fornecidos para o Next.js e ampliar nossos esforços para incluir utilitários semelhantes em outros frameworks e plataformas de CMS. No momento, estamos em colaboração com os mantenedores do Nuxt e planejamos lançar utilitários de terceiros semelhantes adaptados ao ecossistema deles em breve.

Se uma das partes de terceiros que você usa no seu app Next.js tiver suporte para @next/third-parties, instale o pacote e teste. Queremos saber sua opinião no GitHub.