Skip to content

Publique um jogo para web que carregue rápido (um checklist prático)

Se os jogadores não conseguem começar a jogar em poucos segundos, eles desistem. Este tutorial é um checklist prático que você pode aplicar a praticamente qualquer stack de jogos para web (Canvas/WebGL/WebGPU, Pixi/Three/PlayCanvas, engine própria etc.).

1) Defina os limites primeiro (ou você não conseguirá otimizar)

Escolha limites adequados ao dispositivo-alvo. Uma boa configuração padrão para uma experiência de “jogar na hora”:

  • JS+CSS enviados: menos de ~300–500 KB com gzip (quanto menor, melhor)
  • Recursos críticos antes da primeira interação: menos de ~2–5 MB compactados
  • Tempo até a primeira interação: menos de ~3–5 segundos em um celular intermediário

Anote esses limites e trate-os como contratos de API.

2) Meça as coisas certas

No Chrome DevTools:

  • Use Performance para capturar uma sessão e inspecionar tarefas longas.
  • Use Network para verificar:
    • tamanho transferido em comparação com o tamanho decodificado
    • cabeçalhos de cache
    • se os recursos são transmitidos progressivamente ou chegam como um único arquivo enorme

Em termos de jogo, acompanhe:

  • Tempo até “O jogador consegue se mover?
  • Tempo até o “Primeiro frame significativo
  • Latência da primeira interação” (interação → frame)

Sua noção de “latência da primeira interação” agora corresponde a uma métrica padrão: a Interaction to Next Paint (INP) substituiu a First Input Delay como uma das Core Web Vitals em março de 2024 e mede o tempo completo entre a interação e a próxima renderização em todas as interações, não apenas na primeira. Procure manter a INP abaixo de 200 ms no 75º percentil, uma referência externa útil para os números de responsividade que você já acompanha.

3) Comprima tudo o que puder

Certifique-se de que sua hospedagem forneça:

  • Brotli (br) para recursos de texto (JS/CSS/HTML/WASM), quando disponível
  • gzip como alternativa

Se sua hospedagem e CDN oferecerem suporte, Zstandard (zstd) agora é uma terceira opção para Content-Encoding. Ele está disponível no Chrome e Edge 123+, Firefox 126+ e Safari 26.3+ (cerca de 80% dos usuários) e pode alcançar taxas de compressão comparáveis às do Brotli com um custo de CPU menor no servidor, o que ajuda com arquivos WASM e JSON grandes. Os navegadores só anunciam Accept-Encoding: zstd por HTTPS, portanto mantenha Brotli e gzip configurados como alternativas para todos os demais.

Em builds com WebAssembly, a compressão muitas vezes faz a diferença entre “instantâneo” e “nunca carrega”.

4) Não baixe o mundo inteiro logo no início

Divida seu jogo em:

  • Inicialização: carregador mínimo + entrada + primeira cena
  • Núcleo: principais sistemas de jogabilidade
  • Opcional: fases extras, itens cosméticos, texturas em alta resolução, áudio bônus etc.

Carregue o conteúdo “Opcional” somente depois que:

  • o jogador já puder jogar e/ou
  • você souber que ele quer esse conteúdo (por exemplo, porque chegou a um menu ou fase)

5) Escolha os formatos de recursos certos

Para a maioria dos jogos para web:

  • Imagens: prefira WebP (ou AVIF, se puder tolerar uma codificação mais lenta) para interfaces e planos de fundo.
  • Áudio: prefira Ogg Vorbis para uso geral; teste AAC nos ecossistemas da Apple.
  • Vídeo: prefira MP4/H.264 pela compatibilidade e WebM quando houver suporte e o arquivo for menor.

Fique atento ao custo de decodificação: um “download menor” ainda pode ser “mais lento para decodificar”.

6) Mantenha sua primeira cena pequena e determinística

Evite o seguinte em sua primeira cena interativa:

  • picos de compilação de shaders
  • uploads de texturas enormes
  • geração procedural que bloqueia a thread principal
  • análise síncrona de blocos JSON com vários megabytes

Especificamente para texturas, distribua KTX2 com supercompressão Basis Universal em vez de PNG ou JPEG. A textura permanece compactada na GPU após o upload (sendo transcodificada para BC7 em desktops ou ASTC em dispositivos móveis durante o carregamento), o que reduz o uso de VRAM de 4 a 8 vezes e torna os uploads muito menos custosos do que decodificar um PNG em tamanho completo e enviar os pixels brutos para a GPU.

Se precisar executar um processamento pesado, faça isso:

  • de forma incremental ao longo dos frames ou
  • em um Worker (quando possível)

7) Use cache de forma agressiva (mas corretamente)

Use cache de longa duração para recursos endereçados por conteúdo:

  • Cache-Control: public, max-age=31536000, immutable

Para os pontos de entrada HTML, mantenha o cache curto para poder publicar atualizações com segurança.

8) Torne as “falhas” rápidas e compreensíveis

Se algo der errado, exiba:

  • uma mensagem de erro clara
  • um botão para tentar novamente
  • um link para relatar o problema

Falhas silenciosas acabam com a confiança.

9) Se você usa threads em Wasm, entenda COOP/COEP

Se sua build depende de SharedArrayBuffer (algo comum em algumas configurações de threading com Wasm), provavelmente serão necessários cabeçalhos de isolamento entre origens:

  • Cross-Origin-Opener-Policy: same-origin
  • Cross-Origin-Embedder-Policy: require-corp

Você tem duas opções para o cabeçalho COEP. require-corp é a opção mais rigorosa, mas exige que todos os recursos de outra origem (texturas de CDN e scripts de terceiros) enviem um cabeçalho Cross-Origin-Resource-Policy; caso contrário, eles serão bloqueados. Cross-Origin-Embedder-Policy: credentialless também libera o SharedArrayBuffer e o isolamento entre origens, mas carrega recursos de outras origens sem credenciais em vez de exigir que eles aceitem isso por meio de CORP. Se você obtém recursos de uma CDN que não controla, credentialless geralmente é o caminho menos trabalhoso.

Faça testes desde o início em sua hospedagem real, pois os cabeçalhos e conteúdos incorporados de terceiros podem causar problemas.

10) Torne o jogo executável sem um SDK

Se você pretende usar o fluxo de trabalho para criadores da Cinevva, procure oferecer:

  • uma única URL que inicialize o jogo de forma confiável
  • nenhum login obrigatório para iniciar uma demonstração
  • controles de entrada previsíveis

Assim, você estará pronto para distribuir seu jogo sem integrar SDKs adicionais.

Relacionado: