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

Lab data is not enough.

I analyze your field data to find the edge cases failing your user experience.

Analyze My Data >>

  • Real User Data
  • Edge Case Detection
  • UX Focused
Adie scripts até que sejam necessáriosCore Web Vitals Adie scripts até que sejam necessários