A republicação pode terminar com sucesso e ainda abrir uma página quebrada: HTML novo pede um chunk antigo que já não existe, CSS antigo estiliza componentes novos ou um service worker continua respondendo com a versão anterior.
O sintoma parece aleatório porque diferentes pessoas, regiões e perfis guardam cópias diferentes. Criar outro slug ou pedir Ctrl+Shift+R transfere o problema para o público; não corrige o contrato de versão.
Este guia mostra como localizar a camada stale, publicar um pacote coerente e provar que visitantes novos e recorrentes recebem a mesma versão.
Separe as camadas antes de culpar o cache
Uma landing page pode ter cópias em pelo menos cinco pontos:
- pasta de build local;
- pacote enviado para publicação;
- cache de CDN ou intermediário;
- cache HTTP do navegador;
CacheStoragecontrolado por service worker.
Há ainda o back-forward cache do navegador, que preserva uma página inteira para navegação de ida e volta. Ele não é a mesma coisa que o cache HTTP.
Registre o caminho observado:
fonte e commit:comando de build:pasta de saída:hash do pacote:Site ID e slug:deploy ID:URL e domínio:arquivo esperado:bytes ou marcador esperado:headers observados:service worker e escopo:Sem essa cadeia, “a versão antiga voltou” mistura hipóteses demais.
Crie um marcador de versão verificável
Antes de republicar, escolha uma evidência que não dependa apenas da aparência:
- hash do commit no HTML;
- identificador da build em uma meta tag;
- nome versionado do bundle;
- texto específico aprovado;
- manifesto de arquivos com hashes.
Não exponha segredo, token, caminho interno ou dado pessoal. O marcador deve permitir responder “qual versão chegou?”, não revelar como acessar o ambiente.
Uma meta tag simples pode ajudar:
<meta name="build-version" content="2026-09-07.1" />O valor precisa vir do processo de build e acompanhar o pacote. Editar a tag manualmente depois da geração pode criar outra divergência.
Faça os nomes acompanharem os bytes
O padrão mais robusto é gerar um novo caminho quando o conteúdo muda:
assets/app.91d22a.jsassets/styles.b73e10.cssassets/hero.045aca.webpO HTML da mesma build referencia exatamente esses nomes. Depois de uma mudança, a build produz novos arquivos e outro HTML:
assets/app.c430ab.jsassets/styles.11e05d.cssA orientação de cache HTTP da MDN recomenda URLs versionadas para conteúdo com max-age longo. Enquanto o arquivo antigo mantém os mesmos bytes, ele continua seguro para documentos antigos que ainda o referenciam.
Evite:
- sobrescrever
app.jssob TTL longo; - usar query string fixa como
?v=1em todas as builds; - renomear só o JavaScript e deixar CSS ou imagens estáveis;
- calcular o nome antes da transformação final;
- misturar saída de duas execuções na mesma pasta;
- editar arquivos dentro de
distdepois do build.
Gere a saída em diretório limpo
Uma build incremental mal configurada pode manter chunks órfãos e fazer o pacote parecer completo. Antes de publicar:
- use o comando de build oficial;
- confirme que a saída foi recriada pelo comando;
- liste HTML, CSS, JavaScript, imagens, fontes e manifests;
- resolva cada referência local;
- procure arquivos ausentes e assets inesperados;
- compacte apenas a saída publicável atual.
Não apague diretórios fora do contrato do projeto. “Limpar a build” significa usar a tarefa prevista pelo framework ou gerar em uma saída isolada, não executar remoção ampla por suposição.
Uma verificação focada pode procurar referências:
rg -n 'src=|href=|url\(|import\(' distComplemente com o build e os testes do projeto. Encontrar texto não garante que todos os imports dinâmicos estejam cobertos.
Publique a Session como uma Version
No Site no Ar, a Session guarda as alterações feitas pelas file tools. O deploy publica o diretório public/, cria uma Version e ativa o conjunto depois que ele está pronto.
write e edit mudam somente os caminhos indicados; um chunk, uma rota ou um service worker antigo continua no Site até ser removido explicitamente com rm no bash, seguido de deploy. Revise a Session inteira antes de publicar a Version.
Para uma landing page com assets, mantenha em public/:
index.htmlassets/app.c430ab.jsassets/styles.11e05d.cssassets/hero.045aca.webpO contrato de Publicação exige public/index.html. O guia de republicação do mesmo Site mostra como preservar Site ID, slug, URL e domínios enquanto a versão muda.
Antes de publicar, compare a saída atual com o estado desejado. No upload completo, confira se o pacote inclui todos os arquivos que devem permanecer. No fluxo incremental do MCP, liste os arquivos com ls no bash, remova cada caminho obsoleto com rm e atualize public/sitemap.xml quando uma rota HTML sair. Só então execute deploy. A remoção muda o conteúdo público; confirme os caminhos exatos e verifique o status terminal do deploy. Não remova public/index.html: publique uma substituição.
Não publique HTML primeiro e assets depois por caminhos independentes. Mesmo uma janela curta permite que o documento novo aponte para um arquivo que ainda não está disponível.
Não sobrescreva assets imutáveis
Se uma resposta usa:
Cache-Control: public, max-age=31536000, immutableo contrato é que aquela URL não mudará enquanto estiver fresca. Corrigir os bytes sob o mesmo nome não força navegadores a buscá-los novamente.
A solução é:
- gerar outro nome para o arquivo corrigido;
- gerar HTML que aponta para esse nome;
- publicar o pacote completo;
- confirmar a URL nova na resposta pública.
O artigo sobre como configurar Cache-Control detalha quando usar revalidação e quando um TTL longo é seguro.
Verifique HTML antes dos subrecursos
O HTML é o mapa da versão. Se ele ainda aponta para app.91d22a.js, limpar somente o cache do JavaScript não fará surgir app.c430ab.js.
Baixe e examine a resposta:
curl -sS -L \ -H 'Accept: text/html' \ -H 'Sec-Fetch-Dest: document' \ -w '\nURL final: %{url_effective}\n' \ https://exemplo.com/ \ -o /tmp/landing-index.htmlrg -n 'build-version|script|stylesheet|assets/' /tmp/landing-index.htmlDepois consulte cada asset referenciado:
curl -sS -L -D - -o /dev/null \ -w '\nURL final: %{url_effective}\n' \ https://exemplo.com/assets/app.c430ab.jscurl -sS -L -D - -o /dev/null \ -w '\nURL final: %{url_effective}\n' \ https://exemplo.com/assets/styles.11e05d.cssUse a URL final e o último bloco de headers para confirmar status, Content-Type, Cache-Control, ETag, Age e o header de cache da CDN quando disponível. Um 200 text/html para uma URL .js é fallback ou erro mascarado, não asset válido.
Use validadores para distinguir cópia de versão
ETag e Last-Modified permitem revalidação condicional. Quando o cliente envia If-None-Match, a origem pode responder 304 se a representação ainda corresponde ao validador.
Compare uma requisição sem condicional com outra usando o valor observado. Não invente o ETag e não presuma que ele é sempre um hash de conteúdo: o RFC trata a tag como um validador opaco.
Também registre:
Agemaior que zero, que indica tempo em cache intermediário;CF-Cache-Statusou equivalente;- redirect para outro hostname;
- diferença entre URL padrão e domínio próprio;
- parâmetros de query presentes no HTML real.
A resposta precisa ser ligada à URL e ao horário do teste. Headers copiados de outra rota não provam o comportamento do documento atual.
Trate service worker como uma origem local
Um service worker pode interceptar requisições e devolver respostas de CacheStorage sem consultar a rede. Por isso, headers da CDN podem estar corretos enquanto a página continua antiga em perfis que instalaram uma versão anterior.
A especificação atual de Service Workers do W3C mantém estados separados para worker em instalação, em espera e ativo. Um worker novo não assume automaticamente todas as páginas já abertas.
Revise:
- URL e escopo do script;
updateViaCache;- nomes dos caches por versão;
- lista de precache;
- limpeza de caches antigos no
activate; - uso de
skipWaiting()eclients.claim(); - comportamento de abas já abertas;
- fallback offline;
- resposta quando um asset saiu do manifesto.
Não adicione skipWaiting() apenas para “forçar atualização”. Ele pode trocar o controlador enquanto uma página carregada ainda espera outra versão dos assets. A decisão precisa considerar compatibilidade entre HTML, worker e bundles.
Diagnostique em ordem
Quando uma versão antiga aparece, siga esta sequência:
1. Prove a fonte e a build
O marcador correto existe na fonte autorizada e no arquivo dentro de dist?
2. Prove os arquivos do Site
public/index.html referencia os mesmos nomes de asset que existem no workspace?
3. Prove o deploy
O deploy terminou em sucesso no Site ID esperado? A URL e o slug foram preservados?
4. Prove a resposta de rede
Um cliente HTTP sem estado recebe o HTML novo e os assets corretos?
5. Prove os caches HTTP
Navegação normal recebe a versão nova? O HTML revalida? Assets novos têm URLs novas?
6. Prove o service worker
DevTools mostra worker ativo? A resposta veio de ServiceWorker? O cache antigo foi removido pela versão correta?
7. Compare domínios e regiões
URL padrão e domínios próprios mostram o mesmo marcador? Há redirect ou proxy com política diferente?
Mude uma variável por vez. Limpar todos os dados do navegador antes de registrar a camada elimina a evidência que mostraria a causa.
Teste visitantes novos e recorrentes
Use uma matriz pequena:
| Cenário | Perfil | Resultado esperado |
|---|---|---|
| primeira visita | limpo | HTML e assets da versão atual |
| retorno | já visitou | HTML descobre a versão atual |
| aba antiga | aberta antes do deploy | comportamento definido e recuperável |
| reload comum | já visitou | nenhuma mistura de versões |
| offline | com service worker | versão e fallback documentados |
| domínio próprio | limpo e recorrente | mesmo marcador da URL padrão |
Percorra também interações que carregam chunks sob demanda. A home pode parecer correta enquanto formulário, modal ou rota secundária ainda pede um arquivo removido.
Faça rollback com outra versão coerente
Rollback não é editar um asset direto na CDN. Recupere a fonte aprovada, gere uma saída limpa e publique outro pacote completo no mesmo Site.
Registre:
versão com problema:sintoma:camada causal:versão restaurada:deploy de rollback:HTML observado:assets observados:service worker observado:URLs verificadas:Se o problema veio de um asset imutável sobrescrito, o rollback precisa usar outra URL. Restaurar os bytes sob o caminho já armazenado deixa parte dos visitantes presa à cópia anterior.
Prompt copiável para o agente
Diagnostique por que esta landing page mostra assets antigos sem criar outro Site.
Fonte e build: [caminhos]Site ID, slug e URL: [valores]Versão esperada: [marcador]
- Compare fonte, saída, pacote, deploy e resposta pública.- Leia o HTML primeiro e liste exatamente os assets referenciados.- Confirme status, Content-Type, Cache-Control, ETag, Age e cache da CDN.- Verifique URL padrão e domínios próprios.- Inspecione service worker, escopo, caches e ciclo de atualização.- Não use hard reload como única prova e não crie outro slug.- Corrija nomes versionados ou política na fonte responsável.- Republique um pacote completo no mesmo Site.- Teste perfis novos, recorrentes e abas antigas antes do handoff.Checklist final
- fonte, build e pacote possuem o mesmo marcador;
- mudança de bytes gera outra URL de asset;
- HTML referencia somente assets da própria build;
- deploy terminou no Site ID correto;
- URL padrão e domínios próprios foram comparados;
- status, tipo, cache e validadores foram registrados;
- assets ausentes não recebem fallback HTML silencioso;
- service worker e
CacheStorageforam inspecionados; - visitantes novos e recorrentes recebem versão coerente;
- chunks tardios e jornadas críticas foram testados;
- rollback gera outro pacote completo;
- nenhum novo slug foi usado para esconder o defeito.
Uma republicação confiável não termina quando os novos arquivos chegam ao servidor. Ela termina quando o HTML público aponta para uma única versão, os caches conseguem descobrir essa versão e perfis antigos não combinam peças de builds diferentes.
