Kutsik Games
Português
Todos os artigos

100 no PageSpeed com WebGL ao vivo, e o pequeno portão por trás disso

O site do nosso estúdio exibe capas de jogos ao vivo, desenhadas com WebGL, e ainda tira 100 nas quatro categorias do PageSpeed Insights, no celular e no computador. Uma das mudanças que nos levaram até lá agora é um pequeno pacote open source: webgl-gate.

O Lighthouse testa o celular na CPU

O PageSpeed Insights mede páginas móveis no SwiftShader, um rasterizador que desenha WebGL no processador em vez da placa de vídeo. Muitas máquinas virtuais, áreas de trabalho remotas e navegadores com aceleração de hardware desligada fazem o mesmo. Ali uma cena WebGL não é apenas lenta: só baixar e analisar o código já consome tempo da thread principal, e o Total Blocking Time mostra isso.

Nosso site redesenhado começou com 78 no celular, e a maior imagem aparecia após 4,2 segundos.

O que mudamos

O celular chegou a 100: maior imagem em 1,7 segundo, Total Blocking Time de 0 ms e nenhum deslocamento de layout. No computador também é 100, com a maior imagem em 0,4 segundo.

Como o portão decide

O portão cria um contexto WebGL descartável, lê o nome do renderizador e procura por SwiftShader, llvmpipe, softpipe e Basic Render. A flag failIfMajorPerformanceCaveat sozinha não basta: nos nossos testes, o Chrome headless no SwiftShader ainda entrega um contexto com ela ativada.

GPU de verdadeApple M2 Pro, ANGLE Metal
10–24 ms
portão aberto → a cena carrega
SwiftShadero rasterizador na CPU usado pelo PageSpeed
1,4–1,7 s
portão fechado → o bundle da cena nunca é baixado
Tempo da verificação no Chrome headless 155 em um Apple M2 Pro.

O número que nos surpreendeu

Numa GPU de verdade, a verificação leva 10–24 ms. No SwiftShader, criar esse primeiro contexto levou 1,4–1,7 segundo da thread principal. A verificação é cara justamente onde a resposta é não. Por isso o webgl-gate espera a página carregar e o navegador ficar ocioso antes de perguntar, e nunca fica no caminho crítico.

Como usar

Instale pelo npm e carregue a cena apenas numa GPU de verdade. Na CPU o import nunca é chamado, então o bundle nunca é baixado.

npm i webgl-gate
import { loadIfFastWebGL } from 'webgl-gate';

const scene = await loadIfFastWebGL(() => import('./scene'));
if (scene) scene.mount(canvas);

Há também um hook para React, useFastWebGL, e receitas prontas para Next.js, three.js, React Three Fiber, Vue, Svelte e MapLibre. O núcleo tem menos de 1 kB.

O que ele não faz

Ele responde a uma única pergunta: GPU ou não. Se você precisa saber quão potente é a GPU, o detect-gpu da pmndrs classifica GPUs por pontuações de benchmark. O veredito ainda não fica salvo entre visitas: uma resposta guardada poderia durar mais que o hardware que descreve.

Pacote no npmCódigo no GitHub