Otimizar o carregamento de scripts de terceiros no Next.js

Entenda a visão por trás do componente Script do Next.js, que oferece uma solução integrada para otimizar o carregamento de scripts de terceiros.

Leena Sohoni
Leena Sohoni

Cerca de 45% das solicitações de sites veiculados em dispositivos móveis e computadores são de terceiros, sendo que 33% são scripts. O tamanho, a latência e o carregamento de scripts de terceiros podem afetar significativamente o desempenho de um site. O componente de script do Next.js vem com práticas recomendadas e padrões integrados para ajudar os desenvolvedores a introduzir scripts de terceiros nos aplicativos, além de resolver possíveis problemas de desempenho de forma imediata.

Scripts de terceiros e o impacto deles na performance

Os scripts de terceiros permitem que os desenvolvedores Web usem soluções atuais para implementar recursos comuns e reduzir o tempo de desenvolvimento. No entanto, os criadores desses scripts geralmente não têm incentivo para considerar o impacto no desempenho do site que os consome. Esses scripts também são uma caixa-preta para os desenvolvedores que os usam.

Os scripts são responsáveis por um número significativo de bytes de terceiros baixados por sites em diferentes categorias de solicitações de terceiros. Por padrão, o navegador prioriza os scripts com base na posição deles no documento, o que pode atrasar a descoberta ou a execução de scripts essenciais para a experiência do usuário.

As bibliotecas de terceiros necessárias para o layout precisam ser carregadas com antecedência para renderizar a página. Os terceiros que não são necessários para a renderização inicial precisam ser adiados para não bloquear outros processamentos na linha de execução principal. O Lighthouse tem duas auditorias para sinalizar scripts que bloqueiam a renderização ou a linha de execução principal.

Auditorias do Lighthouse para eliminar recursos que impedem a renderização e minimizar o uso de terceiros

É importante considerar a sequência de carregamento de recursos da sua página para que os recursos críticos não sejam atrasados e os não críticos não bloqueiem os críticos.

Embora existam práticas recomendadas para reduzir o impacto de terceiros, nem todo mundo sabe como implementá-las para cada terceiro que usa. Isso pode ser complicado porque:

  • Em média, os sites usam de 21 a 23 terceiros diferentes, incluindo scripts, em dispositivos móveis e computadores. O uso e as recomendações podem ser diferentes para cada um.
  • A implementação de muitos terceiros pode variar de acordo com o uso de um framework ou uma biblioteca de IU específicos.
  • Novas bibliotecas de terceiros são lançadas com frequência.
  • Os diferentes requisitos de negócios relacionados ao mesmo terceiro dificultam a padronização do uso pelos desenvolvedores.

Foco do Aurora em scripts de terceiros

Parte da colaboração do Aurora com frameworks e ferramentas da Web de código aberto é fornecer padrões fortes e ferramentas opinativas para ajudar os desenvolvedores a melhorar aspectos da experiência do usuário, como desempenho, acessibilidade, segurança e prontidão para dispositivos móveis. Em 2021, nosso foco foi ajudar as pilhas de frameworks a melhorar a experiência do usuário e as métricas das Core Web Vitals.

Uma das etapas mais importantes para atingir nossa meta de melhorar o desempenho do framework envolveu pesquisar a sequência de carregamento ideal de scripts de terceiros no Next.js. Frameworks como o Next.js estão em uma posição única para fornecer padrões e recursos úteis que ajudam os desenvolvedores a carregar recursos de maneira eficiente, incluindo de terceiros. Estudamos dados abrangentes do HTTP Archive e do Lighthouse para descobrir quais terceiros bloqueiam a renderização com mais frequência em diferentes frameworks.

Para resolver o problema de scripts de terceiros que bloqueiam a linha de execução principal usados em um aplicativo, criamos o componente Script. O componente encapsula recursos de sequenciamento para oferecer aos desenvolvedores controles melhores para o carregamento de scripts de terceiros.

Sequenciamento de scripts de terceiros sem um componente de framework

As orientações disponíveis para reduzir o impacto de scripts que bloqueiam a renderização oferecem os seguintes métodos para carregar e sequenciar scripts de terceiros de maneira eficiente:

  1. Use o atributo async ou defer com tags <script> que instruem o navegador a carregar scripts de terceiros não essenciais sem bloquear o analisador de documentos. Os scripts que não são necessários para o carregamento inicial da página ou para a primeira interação do usuário podem ser considerados não críticos.

       <script src="https://example.com/script1.js" defer></script>
       <script src="https://example.com/script2.js" async></script>
    
  2. Estabeleça conexões antecipadas com as origens necessárias usando preconnect e dns-prefetch. Isso permite que o download de scripts críticos comece mais cedo.

       <head>
           <link rel="preconnect" href="http://PreconnThis.com">
           <link rel="dns-prefetch" href="http://PrefetchThis.com">
       </head>
    
  3. Use o carregamento lento para recursos e incorporações de terceiros depois que o conteúdo da página principal for carregado ou quando o usuário rolar para baixo até a parte da página em que eles estão incluídos.

O componente Script do Next.js

O componente de script do Next.js implementa os métodos acima para sequenciar scripts e fornece um modelo para que os desenvolvedores definam a estratégia de carregamento. Depois que a estratégia adequada for especificada, ele será carregado de maneira ideal sem bloquear outros recursos críticos.

O componente Script é baseado na tag HTML <script> e oferece uma opção para definir a prioridade de carregamento de scripts de terceiros usando o atributo strategy.

// Example for beforeInteractive:
<Script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=IntersectionObserverEntry%2CIntersectionObserver" strategy="beforeInteractive" />

// Example for afterInteractive (default):
<Script src="https://example.com/samplescript.js" />

// Example for lazyonload:
<Script src="https://connect.facebook.net/en_US/sdk.js" strategy="lazyOnload" />

O atributo strategy pode ter três valores.

  1. beforeInteractive: essa opção pode ser usada para scripts críticos que precisam ser executados antes que a página se torne interativa. O Next.js garante que esses scripts sejam injetados no HTML inicial no servidor e executados antes de outros JavaScripts autoempacotados. O gerenciamento de consentimento, os scripts de detecção de bots ou as bibliotecas auxiliares necessárias para renderizar conteúdo crítico são bons candidatos para essa estratégia.

  2. afterInteractive: essa é a estratégia padrão aplicada e equivale a carregar um script com o atributo defer. Ele deve ser usado para scripts que o navegador pode executar depois que a página se torna interativa, como scripts de análise. O Next.js injeta esses scripts no lado do cliente, e eles são executados depois que a página é hidratada. Portanto, a menos que especificado de outra forma, todos os scripts de terceiros definidos usando o componente Script são adiados pelo Next.js, o que fornece um padrão forte.

  3. lazyOnload: essa opção pode ser usada para carregar lentamente scripts de baixa prioridade quando o navegador está inativo. A funcionalidade fornecida por esses scripts não é necessária imediatamente após a página se tornar interativa, por exemplo, plug-ins de chat ou de redes sociais.

Os desenvolvedores podem informar ao Next.js como o aplicativo usa um script especificando a estratégia. Isso permite que o framework aplique otimizações e práticas recomendadas para carregar o script, garantindo a melhor sequência de carregamento.

Usando o componente Script, os desenvolvedores podem colocar um script de terceiros em qualquer lugar do aplicativo para terceiros de carregamento tardio e no nível do documento para scripts críticos. Isso significa que o componente Script pode ser colocado no mesmo local que o componente que usa o script. Após a hidratação, o script será injetado no cabeçalho do documento renderizado inicialmente ou na parte de baixo do corpo, dependendo da estratégia usada.

Medição do impacto

Usamos os modelos do app de comércio e do blog inicial do Next.js para criar dois apps de demonstração que ajudaram a medir o impacto da inclusão de scripts de terceiros. Os terceiros usados com frequência para o Google Tag Manager e as incorporações de rede social foram incluídos nas páginas desses apps diretamente no início e, depois, pelo componente Script. Em seguida, comparamos o desempenho dessas páginas no WebPageTest.

Scripts de terceiros em um app de comércio Next.js

Os scripts de terceiros foram adicionados ao modelo do app de comércio para a demonstração, conforme mostrado abaixo.

Antes Depois
Google Tag Manager com async Componente de script com strategy = afterInteractive para os dois scripts
Botão "Seguir" do Twitter sem async ou defer
Configuração do script e do componente de script para a demonstração 1 com dois scripts.

A comparação a seguir mostra o progresso visual das duas versões do kit inicial de comércio do Next.js. Como mostrado, a LCP ocorre quase 1s antes com o componente Script ativado com a estratégia de carregamento certa.

Comparação de tiras de filme mostrando melhoria na LCP

Scripts de terceiros em um blog do Next.js

Os scripts de terceiros foram adicionados ao app de blog de demonstração, conforme mostrado abaixo.

Antes Depois
Google Tag Manager com async Componente de script com strategy = lazyonload para cada um dos quatro scripts
Botão "Seguir" do Twitter com async
Botão "Inscrever-se" do YouTube sem async ou defer
Botão "Seguir" do LinkedIn sem async ou defer
Configuração de script e componente de script para a demonstração 2 com 4 scripts.
Vídeo mostrando o progresso do carregamento da página de índice com e sem o componente Script. Há uma melhoria de 0,5 segundo na FCP com o componente Script.

Como mostrado no vídeo, a First Contentful Paint (FCP) ocorre em 0,9 segundo na página sem o componente Script e em 0,4 segundo com o componente Script.

Próximas etapas do componente Script

Embora as opções de estratégia para afterInteractive e lazyOnload ofereçam um controle significativo sobre os scripts que bloqueiam a renderização, também estamos explorando outras opções que aumentariam a utilidade do componente Script.

Como usar workers da web

Os web workers podem ser usados para executar scripts independentes em linhas de execução em segundo plano, o que pode liberar a linha de execução principal para processar tarefas da interface do usuário e melhorar o desempenho. Os workers da Web são mais adequados para transferir o processamento de JavaScript, em vez do trabalho de interface, da linha de execução principal. Scripts usados para suporte ao cliente ou marketing, que normalmente não interagem com a IU, podem ser bons candidatos para execução em uma linha de execução em segundo plano. Uma biblioteca leve de terceiros, a PartyTown, pode ser usada para isolar esses scripts em um worker da Web.

Com a implementação atual do componente de script do Next.js, recomendamos adiar esses scripts na linha de execução principal definindo a estratégia como afterInteractive ou lazyOnload. No futuro, propomos introduzir uma nova opção de estratégia, 'worker', que permitirá que o Next.js use o PartyTown ou uma solução personalizada para executar scripts em workers da Web. Comentários de desenvolvedores sobre essa RFC são bem-vindos.

Como minimizar a CLS

Incorporações de terceiros, como anúncios, vídeos ou feeds de rede social, podem causar mudanças de layout quando carregadas lentamente. Isso afeta a experiência do usuário e a métrica Cumulative Layout Shift (CLS) da página. A CLS pode ser minimizada especificando o tamanho do contêiner em que a incorporação será carregada.

O componente Script pode ser usado para carregar incorporações que podem causar mudanças de layout. Estamos considerando aumentar o recurso para fornecer opções de configuração que ajudem a reduzir a CLS. Isso pode ser disponibilizado no próprio componente Script ou como um componente complementar.

Componentes de wrapper

A sintaxe e a estratégia de carregamento para incluir scripts de terceiros conhecidos, como o Google Analytics ou o Google Tag Manager (GTM), geralmente são fixas. Eles podem ser encapsulados em componentes de wrapper individuais para cada tipo de script. Apenas um conjunto mínimo de atributos específicos do aplicativo (como o ID de rastreamento) estará disponível para os desenvolvedores. Os componentes wrapper vão ajudar os desenvolvedores:

  1. Facilitar a inclusão de tags script conhecidas.
  2. Garantir que o framework use a estratégia mais ideal em segundo plano.

Conclusão

Os scripts de terceiros geralmente são criados para incluir recursos específicos no site que os consome. Para reduzir o impacto de scripts não críticos, recomendamos adiá-los, o que o componente de script do Next.js faz por padrão. Os desenvolvedores têm a garantia de que os scripts incluídos não vão atrasar funcionalidades críticas, a menos que apliquem explicitamente a estratégia beforeInteractive. Assim como o componente de script do Next.js, os desenvolvedores de frameworks também podem criar esses recursos em outros frameworks. Estamos analisando ativamente a possibilidade de lançar um componente semelhante com a equipe do Nuxt.js. Com base no feedback, também esperamos melhorar ainda mais o componente Script para abranger outros casos de uso.

Agradecimentos

Agradecemos a Kara Erickson, Janicklas Ralph, Katie Hempenius, Philip Walton, Jeremy Wagner e Addy Osmani pelo feedback sobre esta postagem.