Adie scripts até que sejam necessários

Aprenda como corrigir os Core Web Vitals adiando scripts até que sejam necessários

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2024-11-27

Adie scripts até que sejam necessários

Neste artigo vou mostrar e explicar um padrão interessante para carregar scripts que não são necessários durante o início do carregamento da página em um momento posterior, logo antes de serem necessários.

A coisa mais eficaz que você pode fazer com JavaScript quando se trata dos Core Web Vitals é adiar o carregamento de um recurso até que ele seja necessário. Isso removerá JavaScript não utilizado e desnecessário da página e só o carregará quando for necessário. Isso corrigirá o aviso do Lighthouse 'reduce unused JavaScript' e também melhorará métricas de responsividade como o Interaction to Next Paint (INP).
Fazemos isso com imagens há muito tempo. Chama-se lazy loading. Com lazy loading, uma imagem abaixo da dobra é carregada logo antes de entrar na área visível. Dessa forma, não precisamos carregar a imagem imediatamente durante o carregamento da página e o navegador pode gastar seus recursos preciosos baixando, analisando e renderizando coisas que são realmente necessárias.

Agora imagine que poderíamos fazer a mesma coisa com scripts em vez de imagens. Pois acontece que podemos! Infelizmente não é tão simples quanto adicionar loading="lazy" a uma imagem, mas com um pouco de esforço podemos fazê-lo funcionar

Passo 1: Carregar scripts sob demanda

Para adicionar scripts à página após o carregamento da página, precisaremos de um pequeno script que faça isso por nós.

function injectScript(scriptUrl, callback) {
  var script = document.createElement("script");
  script.src = scriptUrl;
  if (typeof callback === "function") {
    script.onload = function () {
      callback();
    };
  }
  document.head.appendChild(script);
}        

Esta função injeta um script na página web atual criando um novo elemento script e adicionando-o ao head do documento. O parâmetro scriptUrl especifica a URL do script a ser injetado. O parâmetro callback é uma função opcional que será chamada quando o script terminar de carregar. Quando o script terminar de carregar, o evento onload do elemento script é disparado. Se uma função callback foi fornecida, ela será chamada nesse momento.

Passo 2: Carregar scripts sob demanda

O próximo passo é carregar scripts sob demanda. Existem 2 métodos comuns de fazer isso. O primeiro é o mais confiável 'quando uma parte da página está visível' e o segundo é o mais rápido 'na interação'.

2a: Intersection observer

O primeiro método para carregar um script logo antes de ser necessário utiliza o intersection observer. O intersection observer é um método confiável que 'dispara' quando um elemento está intersectando com a parte visível da tela. Podemos usar esse comportamento para acionar o download de um script apenas quando um elemento está visível. A desvantagem desse método é que, embora um elemento esteja 'na tela', ele ainda pode não ser utilizado.

function injectScriptOnIntersection(scriptUrl, elementSelector) {
  var observer = new IntersectionObserver(function(entries, observer) {
    entries.forEach(function(entry) {
      if (entry.isIntersecting) {
        injectScript(scriptUrl);
        observer.unobserve(entry.target);
      }
    });
  });

  var element = document.querySelector(elementSelector);
  observer.observe(element);
}
        

Esta função recebe dois parâmetros: scriptUrl é a URL do script a ser injetado, e elementSelector é um seletor CSS para o elemento que deve acionar a injeção.

A função cria um novo objeto IntersectionObserver e passa uma função callback que será chamada sempre que um elemento observado intersectar com o viewport. A função callback verifica se o elemento está intersectando e, se sim, injeta o script e para de observar o elemento.

Note que a Intersection Observer API não é suportada em todos os navegadores, então você pode precisar usar um polyfill se precisar suportar navegadores mais antigos.

injectScriptOnIntersection('script.js', '#my-element');

Isso injetará o script quando o elemento com ID my-element se tornar visível no viewport.

2b: Na interação

O método mais eficaz para carregar JavaScript sob demanda é carregá-lo quando um visitante interage com um determinado elemento. Por exemplo, um formulário. A vantagem de usar esse método é que você provavelmente nunca carregará o script se ele não for necessário. A desvantagem é que a ação de download é bastante tardia e temos que decidir quais eventos (mouseover, hover, touchstart etc etc) queremos escutar.

function injectScriptOnInteraction(scriptUrl, elementSelector, eventTypes) {
  var element = document.querySelector(elementSelector);
  var eventHandler = function() {
    injectScript(scriptUrl);
    eventTypes.forEach(function(eventType) {
      element.removeEventListener(eventType, eventHandler);
    });
  };
  eventTypes.forEach(function(eventType) {
    element.addEventListener(eventType, eventHandler);
  });
}
        

Esta função recebe três parâmetros: scriptUrl é a URL do script a ser injetado, elementSelector é um seletor CSS para o elemento que deve acionar a injeção, e eventTypes é um array de tipos de eventos que devem acionar a injeção (ex.: ["click", "mouseover"]).

A função encontra o elemento usando document.querySelector e adiciona event listeners para cada um dos tipos de eventos especificados. Quando qualquer um dos eventos especificados ocorre, a função injectScript é chamada com a URL especificada, e os event listeners são removidos usando element.removeEventListener.

injectScriptOnInteraction(
  'script.js',
  '#my-element', 
  ['click', 'mouseover']
);

Isso injetará o script quando o elemento com ID my-element for clicado ou o mouse passar sobre ele, e então removerá os event listeners.

Conclusão

Quando scripts não são necessários logo no início do carregamento da página, é uma ótima ideia carregá-los sob demanda! Podemos fazer isso usando o intersection observer ou na interação. Isso liberará recursos valiosos durante os estágios iniciais do carregamento da página

The RUM tool I built for my own clients.

CoreDash is what I use to audit enterprise platforms. Under 1KB tracking script, EU hosted, no consent banner. AI with MCP support built in. The same tool, available to everyone.

Create Free Account
Adie scripts até que sejam necessáriosCore Web Vitals Adie scripts até que sejam necessários