neptay
Todos os insights

Engenharia

Um site de estúdio em menos de 1 s: o orçamento de desempenho que seguimos

Como entregamos sites de estúdio que exibem o primeiro conteúdo em menos de um segundo num celular intermediário em 4G — o orçamento que nos impomos, o que fica de fora e as pequenas decisões de arquitetura que mais importam para as Core Web Vitals.

Neste artigo

Existe um tipo específico de site de estúdio — aquele em que cada rolagem dispara um brilho em parallax, uma troca de fonte, um reel em autoplay que fica três segundos carregando e um cursor que ganha presas no hover — que leva oito segundos para carregar num celular intermediário e parece quebrado em qualquer conexão que não seja fibra. Nós não entregamos esse tipo de site. O briefing que nos impomos é brutal e simples: first contentful paint em menos de um segundo, num Pixel 6a, numa conexão 4G com velocidade limitada.

Cumprir esse briefing não depende de otimizações heroicas. Depende de um pequeno número de escolhas de arquitetura que se somam, e de um número muito maior de coisas que não fazemos. Este artigo traz o orçamento com que trabalhamos, as decisões por trás dele e as medições de campo que provam que o orçamento se manteve. Se você está lançando um site de estúdio, de agência ou qualquer superfície com cara de portfólio, esta é uma meta real que você pode copiar quase inteira.

O orçamento, em números

Todo site de estúdio que entregamos mira estes números num Pixel 6a com Fast 3G no throttling do Chrome DevTools. Na prática, uma conexão 4G é mais rápida; usamos o Fast 3G como limite inferior de pior caso. Medimos com o Lighthouse e com métricas de usuários reais em produção, via Vercel Analytics.

  • Largest Contentful Paint (LCP): abaixo de 1,2 s em laboratório e abaixo de 1,8 s no p75 em campo. O limite “bom” do Google é 2,5 s.
  • First Contentful Paint (FCP): abaixo de 1,0 s em laboratório.
  • Cumulative Layout Shift (CLS): abaixo de 0,05. O limite “bom” do Google é 0,1; nós nos impomos a metade disso.
  • Interaction to Next Paint (INP): abaixo de 100 ms. O limite “bom” do Google é 200 ms.
  • Tamanho total transferido no primeiro carregamento: abaixo de 150 KB comprimidos, incluindo HTML, CSS, fontes, JS e a imagem hero.
  • Bundle de JavaScript no primeiro carregamento: abaixo de 80 KB comprimidos.

Se uma página não atinge qualquer um desses números, tratamos como bug P1. Não como “algo para ver depois”. Um P1 que corrigimos antes de o site ir ao ar.

Por que tanto rigor?

Dois motivos. Primeiro, as Core Web Vitals são um fator de ranqueamento do Google. Não um critério de desempate — um fator de ranqueamento. Sites que atingem os limites se qualificam para o impulso de experiência na página; os que não atingem são penalizados na margem. Para um estúdio que disputa grupos estreitos de palavras-chave, a margem importa.

Segundo, o desempenho percebido é um sinal de marca. Um site que carrega na hora transmite competência. Um site que trava enquanto um pixel de rastreamento carrega transmite o contrário. Para um estúdio cujo discurso inteiro é “entregamos trabalho moderno e bem pensado”, o site precisa demonstrar esse discurso no primeiro contato. O site é o briefing.

Decisão 1: Renderizar tudo estaticamente

A maior decisão de desempenho é a estratégia de renderização. Usamos Next.js com o App Router, e todas as páginas dos nossos sites de estúdio são renderizadas estaticamente no build. Sem consultas a banco de dados em tempo de execução. Sem trabalho de servidor por requisição além da edge function que serve o HTML. O site inteiro são arquivos numa CDN.

O que você ganha com isso, concretamente: o TTFB na edge é o que a sua CDN disser — normalmente de 30 a 80 ms em qualquer lugar do planeta. O primeiro byte de HTML chega antes de o navegador terminar o handshake TLS numa alternativa renderizada no servidor. Tudo o que vem depois — renderização, interatividade, a próxima página — começa bem antes.

A contrapartida é que mudanças de conteúdo exigem um deploy. Para um site de estúdio atualizado mensalmente, um deploy não é nada — leva 90 segundos na Vercel. Para uma publicação atualizada de hora em hora, a conta é outra, e o ISR (Incremental Static Regeneration) é a ferramenta certa. Mas sites de estúdio não são atualizados de hora em hora.

Decisão 2: Uma fonte web, dois pesos

Fontes personalizadas são o maior custo controlável na primeira renderização. Um subset de fonte web para um único peso costuma ter de 25 a 40 KB comprimidos. Um site que carrega três pesos de duas famílias envia 150 KB de fontes antes que o primeiro byte de conteúdo apareça. Nós enviamos uma família em dois pesos, servida pela entrega auto-hospedada e com hash do next/font — sem requisição de terceiros ao Google Fonts, sem consulta DNS a uma CDN de fontes.

Também aceitamos a consequência: não há itálico, nem thin, nem extrabold. Toda distinção tipográfica precisa ser feita com tamanho, cor, espaçamento entre letras ou contraste entre os dois pesos que temos. É uma restrição criativa que se paga. Sites que precisam de oito pesos costumam esconder uma hierarquia fraca sob variedade tipográfica; sites que funcionam com dois pesos precisam conquistar a hierarquia na estrutura.

Decisão 3: O orçamento do hero — e como gastá-lo

Num site de estúdio, o LCP é quase sempre o hero. Então o orçamento de LCP é o orçamento do hero. Damos ao hero um teto rígido: 80 KB comprimidos no breakpoint de desktop, 40 KB no celular. Qualquer coisa maior é um desafio criativo a resolver na escolha ou no tratamento da imagem, não uma desculpa para estourar o orçamento.

Quatro práticas que nos mantêm dentro do orçamento:

  1. Usar AVIF onde houver suporte, com fallback em WebP. O AVIF costuma ser 30–40% menor que o WebP com qualidade equivalente.
  2. Servir tamanhos responsivos com o componente next/image. Celulares nunca baixam o hero de desktop; desktops nunca baixam a versão retina 2x, a menos que a tela seja de fato retina.
  3. Definir width e height explícitos em toda imagem. É isso que evita o deslocamento de layout — o navegador reserva o número certo de pixels antes de a imagem chegar.
  4. Fazer preload da imagem hero. <link rel="preload" as="image" href="…"/> no head. Custa uma linha e economiza de 200 a 400 ms no LCP, porque o navegador inicia a requisição da imagem antes de analisar o resto da página.

Decisão 4: JavaScript como último recurso

Cada kilobyte de JavaScript é um kilobyte que precisa ser baixado, analisado e executado na thread principal antes de a página ficar interativa. Tratamos o orçamento de JS como escasso e seguimos duas regras:

  • Server components por padrão. Só marque um componente com 'use client' se ele realmente precisar de interatividade. O padrão dos React Server Components é o padrão certo para sites com muito conteúdo.
  • Nenhum script de terceiros no primeiro carregamento. Nada de analytics que envia 80 KB de código de fornecedor. Nada de gerenciadores de tags. O analytics é carregado sob demanda depois que a página fica interativa — usamos o Vercel Analytics, que pesa cerca de 1 KB.

O orçamento que impomos aos nossos sites de estúdio é de menos de 80 KB de JS comprimido no primeiro carregamento — a maior parte é o próprio React. A camada interativa (menu de navegação, seletor de idioma, formulário de contato) ocupa poucos kilobytes.

Decisão 5: Uma arquitetura de CSS sem bugs de deslocamento de layout

O Cumulative Layout Shift é a Core Web Vital mais fácil de reprovar por acidente e a mais fácil de corrigir de propósito. Os quatro hábitos que mantêm o CLS perto de zero:

  1. Reservar espaço para tudo o que chega tarde. Imagens, fontes, iframes, anúncios — tudo ganha um contêiner com aspect-ratio e dimensões explícitas.
  2. Evitar CSS que dependa do carregamento da fonte. Use fontes do sistema como fallback durante a janela de troca, com font-display: swap. Escolha um fallback com métricas iguais às da fonte web para que a troca fique invisível.
  3. Não injetar conteúdo acima da dobra depois do carregamento. Banners, avisos de cookies e barras de avisos que surgem depois da primeira renderização são um deslocamento de layout esperando para acontecer. Se precisar deles, renderize-os no HTML inicial e anime a entrada.
  4. Testar em redes lentas. Problemas de CLS que não aparecem na fibra aparecem no 3G, porque o recurso que chega tarde chega ainda mais tarde.

Decisão 6: O orçamento de animação

Contenção no movimento é, por si só, uma otimização de desempenho. Toda animação que roda na thread principal arrisca uma regressão de INP — uma única animação travada de 250 ms num clique tira o site inteiro da faixa “boa” de INP. Nossas regras:

  • Animar apenas transform e opacity. Ambas são compostas pela GPU e não disparam layout.
  • Animações de entrada são CSS, não JavaScript. Usamos um IntersectionObserver para adicionar um className; a animação em si é uma transition.
  • Nada de animações atreladas à rolagem. Parecem elegantes e entregam um desempenho de rolagem péssimo em aparelhos intermediários.
  • Nada de vídeo em autoplay no hero. Se o vídeo for necessário, carregue-o sob demanda abaixo da dobra ou atrás de uma interação.

Decisão 7: Onde acessibilidade e desempenho se encontram

A maioria dos ganhos de acessibilidade também é ganho de desempenho. HTML semântico é menor que uma sopa de divs. Anéis de foco nativos renderizam mais rápido que um gerenciamento de foco customizado em JS. Skip links no cabeçalho dispensam correções de armadilhas de teclado que enviam JavaScript. Projetamos e construímos pensando primeiro em acessibilidade; o desempenho vem de graça.

O único ponto em que desempenho e acessibilidade entram em tensão é a animação. Alguns usuários precisam de movimento; outros ficam enjoados. Respeitamos o prefers-reduced-motion e entregamos toda animação de entrada com um fallback que é um fade — não um translate.

Medição em produção

Métricas de laboratório do Lighthouse são necessárias, mas não suficientes. O padrão-ouro é o monitoramento de usuários reais (RUM) — o que visitantes reais vivem em aparelhos reais. Usamos o Vercel Analytics para as Web Vitals porque ele vem de graça com a plataforma e reporta métricas de campo segmentadas por rota, dispositivo e região.

O que olhamos toda semana:

  • LCP p75 por rota. Se o p75 de qualquer rota passar de 1,8 s, investigamos.
  • Regressões de INP. O INP é a métrica mais traiçoeira — ele pode piorar silenciosamente à medida que o JavaScript cresce.
  • CLS por rota. Regressões de CLS geralmente vêm de um único elemento que carrega tarde.
  • JS do primeiro carregamento por rota, acompanhado pelo bundle analyzer no CI. Reprovamos os builds que estouram o orçamento.

O que não fazemos

Tão importante quanto — as coisas que deixamos de fora de propósito, mesmo sendo padrão do mercado:

  • Nada de roteamento no cliente ao estilo SPA num site pequeno. Buscar o documento completo é mais rápido que o delta do bundle numa conexão 4G. Deixamos o navegador navegar.
  • Nada de service worker. A complexidade não compensa num site com menos de 10 páginas.
  • Nada de serviço de hospedagem de imagens que injeta um SDK de 30 KB. Servimos as imagens do mesmo domínio do site, otimizadas no build.
  • Nada de biblioteca “inteligente” de lazy-load. O atributo nativo loading="lazy" faz o trabalho com 0 KB.
  • Nada de prefetch de todos os links no hover. O Next.js faz prefetch por padrão em produção; deixamos isso ativado e deixamos o framework decidir.

Se você está definindo o escopo de um site e quer uma auditoria de desempenho do que já tem, ou quer um site construído com este orçamento desde o início: hello@neptay.com.

Neptay Media & Technology Services

Vamos conversar

Planejando algo parecido?

Os métodos destes artigos são os mesmos que usamos em projetos de clientes — software, automação com IA, conteúdo, redes sociais e produção de lives. Conte o que você tem em mente; respondemos em até 24 horas.