Sites estáticos agora continuam no ar enquanto são publicados de novo
Publicar de novo um site estático no Mythex costumava apagar primeiro os arquivos no ar e só depois enviar o novo build. Assim, durante o upload, alguns visitantes recebiam uma página 404 ou uma página cujos scripts estavam faltando. Um upload que falhava podia deixar o site vazio ou meio novo. Agora o novo build é gravado por cima do antigo, com as páginas por último, e os restos são removidos alguns minutos depois. Uma segunda correção faz a nova publicação aparecer em segundos, e não em um minuto; ou, para arquivos como um logotipo, em até um dia.
Como um site estático é servido
Um site estático é feito só de arquivos: páginas HTML, JavaScript, CSS, imagens. Quando você publica um no Mythex, nós o construímos, enviamos o resultado para um armazenamento de objetos, numa pasta do seu site, e o servimos por uma rede de borda: servidores próximos aos seus visitantes que buscam os arquivos no armazenamento e guardam cópias deles por um tempo. (Se isso for novidade para você, nosso guia sobre o que é uma CDN explica a ideia.)
Duas coisas estavam erradas: a ordem em que uma nova publicação trocava os arquivos e o tempo que as cópias antigas eram mantidas.
Problema 1: o upload esvaziava o site primeiro
Uma nova publicação apagava tudo na pasta do site e então enviava o novo build. Durante todo o tempo do upload (12 segundos para um site de 250 arquivos no nosso teste local), um visitante cuja requisição não estivesse em cache na borda recebia um 404, ou uma página HTML cujos scripts devolviam 404.
Um upload que falhava era pior. A pasta já estava vazia, e em um dos dois caminhos de upload o novo index.html podia entrar antes do arquivo que falhou. Uma publicação informada como falha podia deixar no ar um site meio novo.
A correção: gravar por cima, páginas por último, limpar depois
- Não apague antes. O novo build é enviado por cima do antigo.
- Recursos antes das páginas. Uma página indica os scripts e estilos de que precisa, então as páginas sobem por último. Até as novas páginas chegarem, os visitantes recebem a página antiga, que aponta para os recursos antigos, que ainda estão lá. Quando as novas chegam, os novos recursos que elas citam já estão no lugar.
- Remova os restos depois. Antes do upload, listamos do que o site é feito. Três minutos depois de um upload bem-sucedido, tudo o que estiver nessa lista e que o novo build não reescreveu é apagado. Três minutos é mais que os 60 segundos em que uma página poderia ficar em cache na borda e no navegador, então um visitante que ainda tenha a página antiga consegue encontrar os recursos que ela cita.
- Na dúvida, não apague nada. Se a listagem antes do upload falhar, nada é limpo. Arquivos sobrando são inofensivos, e a próxima publicação os remove. Apagar sem saber o que estava ali é como um site acaba vazio.
Um upload que falha agora deixa o site anterior exatamente como estava.
Testamos isso de ponta a ponta localmente, usando o script de upload real, a rota de upload real e o serviço de armazenamento real, com visitantes chegando com cache de borda frio. Com o código antigo, 55 de 91 visitas quebraram durante uma publicação, e 61 de 92 durante uma que falhou. Com o código novo, 0 quebraram em cerca de 3.500 visitas cobrindo os dois caminhos de upload, um upload que falhou e a publicação seguinte, e apenas os arquivos sobrando foram removidos.
Problema 2: uma publicação demorava para aparecer
Mesmo quando o upload dava certo, as mudanças demoravam a aparecer. A borda mantinha sua cópia de uma página por 60 segundos e de todos os outros arquivos por um dia, e dizia aos navegadores para fazerem o mesmo. Arquivos com nome fixo, como logo.png, uma fonte, qualquer coisa de uma pasta public/, podiam mostrar a versão antiga por até um dia depois de uma publicação.
A correção: cópias de arquivos atreladas ao build
Quando a borda pergunta à nossa API onde um site está, a resposta agora inclui um marcador de build que muda a cada publicação. A borda guarda suas cópias sob esse marcador. Assim, uma publicação vira um conjunto totalmente novo de chaves de cache assim que a consulta de 30 segundos da borda expira. As cópias antigas simplesmente deixam de ser encontradas, então a borda pode manter cópias por um dia sem nunca servir uma que tenha sido substituída por uma publicação posterior.
Os navegadores recebem duas regras diferentes:
- Saída de build com hash, como arquivos do tipo
assets/index-CzLcxDO8.js, cujo nome muda sempre que o conteúdo muda, fica em cache por um ano e é marcada como imutável. Sob esse nome, nunca fica desatualizada. - Todo o resto, páginas e arquivos de nome fixo como um logotipo, é marcado como
no-cache, que significa “verifique antes de usar”. Se nada mudou, a resposta é um304 Not Modifiedpequeno, sem corpo, já que agora respeitamos a verificaçãoIf-None-Matchdo navegador.
Distinguir os dois casos exige cuidado: um arquivo copiado de public/assets/ mantém o próprio nome, e colocar assets/logo.png em cache por um ano fixaria o logotipo antigo por um ano. Então um arquivo só conta como hash se estiver numa pasta de saída de build e o nome tiver um segmento que parece um hash, não uma palavra comum.
Localmente, a nova página e o novo logotipo ficaram visíveis 6 segundos depois que a publicação foi ao ar. Antes, eram 60 segundos para a página e um dia para o logotipo.
Duas correções menores no caminho
- Páginas em branco em requisições HEAD. Uma requisição
HEADpede os cabeçalhos de uma página sem o corpo. Estávamos guardando essas respostas vazias em cache, então o próximo visitante daquela página recebia uma página em branco. RespostasHEADnão são mais armazenadas em cache. - Uma página real para “não há nada aqui”. Um endereço sem app costumava receber um texto simples “Este app publicado está offline ou o link não foi encontrado”, com código de erro 502. Agora recebe uma página adequada, “Não há nenhum app aqui”, com status 404 e um caminho de volta ao Mythex para o dono. Domínios personalizados desconhecidos recebem a mesma página.
O que tiramos disso
- A ordem faz parte da correção. Os mesmos arquivos enviados em outra ordem fazem a diferença entre um site quebrado e um que funciona.
- Apague tarde, e só o que você conhece. Limpar com uma listagem feita antes do upload é seguro; esvaziar uma pasta e torcer para o upload terminar não é.
- Faça cache por versão, não por tempo. Tempos de expiração são um palpite sobre quando o conteúdo muda. Uma chave que muda com o build é um fato.
Relacionado: seu app publicado agora continua no ar enquanto você o publica de novo. Mais sobre publicação na documentação.