Blogue

Os Sites Estáticos Continuam no Ar Enquanto Republicam

Republicar um site estático no Mythex apagava antes os ficheiros em produção e só depois enviava a nova compilação, por isso, durante o envio, alguns visitantes recebiam uma página 404 ou uma página cujos scripts estavam em falta. Um envio falhado podia deixar o site vazio ou meio novo. Agora a nova compilação é escrita por cima da antiga, com as páginas por último, e os restos são removidos alguns minutos depois. Uma segunda correção faz com que uma republicação apareça em segundos em vez de um minuto — ou, para ficheiros como um logótipo, até um dia.

Como um site estático é servido

Um site estático é apenas ficheiros: páginas HTML, JavaScript, CSS, imagens. Quando publicas um no Mythex, nós compilamos, enviamos o resultado para armazenamento de objetos numa pasta do teu site e servimo-lo através de uma rede de borda — servidores próximos dos teus visitantes que vão buscar os ficheiros ao armazenamento e guardam cópias durante algum tempo. (Se isto for novo para ti, o nosso guia sobre o que é uma CDN explica a ideia.)

Havia duas coisas erradas: a ordem pela qual uma republicação alterava os ficheiros e durante quanto tempo as cópias antigas eram mantidas.

Problema 1: o envio esvaziava o site primeiro

Uma republicação apagava tudo na pasta do site e só depois enviava a nova compilação. Durante o tempo que o envio demorava — 12 segundos para um site de 250 ficheiros no nosso teste local — um visitante cujo pedido não estivesse já em cache na borda recebia um 404, ou uma página HTML cujos scripts devolviam 404.

Um envio falhado era pior. A pasta já estava vazia, e numa das duas vias de envio o novo index.html podia ficar gravado antes do ficheiro que falhou. Uma publicação reportada como falhada podia deixar um site meio novo em produção.

A correção: escrever por cima, páginas por último, limpar depois

  1. Não apagar primeiro. A nova compilação é enviada por cima da antiga.
  2. Recursos antes das páginas. Uma página indica os scripts e estilos de que precisa, por isso as páginas sobem por último. Até as novas páginas chegarem, os visitantes recebem a página antiga, que indica os recursos antigos, que ainda lá estão. Quando chegam, os recursos novos de que precisam já estão no lugar.
  3. Remover os restos mais tarde. Antes do envio, listamos do que o site é feito. Três minutos depois de um envio bem-sucedido, tudo o que estiver nessa lista e que a nova compilação não tenha reescrito é apagado. Três minutos é mais do que os 60 segundos durante os quais uma página pode estar em cache na borda e no browser, por isso um visitante que ainda tenha a página antiga consegue encontrar os recursos que ela referencia.
  4. Na dúvida, não apagar nada. Se a listagem antes do envio falhar, não se remove nada. Os ficheiros que sobram são inofensivos, e a publicação seguinte limpa-os. Apagar sem saber o que lá estava é a forma como um site acaba vazio.

Um envio falhado deixa agora o site anterior exatamente como estava.

Testámos isto de ponta a ponta localmente, com o script de envio real, a rota de envio real e o serviço de armazenamento real, e com visitantes a chegar com a cache de borda vazia. Com o código antigo, 55 de 91 visitas ficaram quebradas durante uma republicação e 61 de 92 durante uma falhada. Com o código novo, 0 ficaram quebradas em cerca de 3.500 visitas, cobrindo as duas vias de envio, um envio falhado e a publicação seguinte — e foram removidos exatamente os ficheiros que sobravam.

Problema 2: uma republicação demorava a aparecer

Mesmo quando o envio corria bem, as alterações demoravam a surgir. A borda guardava a sua cópia de uma página durante 60 segundos e de todos os outros ficheiros durante um dia, e dizia aos browsers para fazerem o mesmo. Ficheiros com nome fixo — logo.png, um tipo de letra, qualquer coisa de uma pasta public/ — podiam mostrar a versão antiga até um dia depois de uma republicação.

A correção: cópias de ficheiros dentro da compilação

Quando a borda pergunta à nossa API onde um site está, a resposta inclui agora um marcador de compilação que muda sempre que uma publicação entra em produção. A borda guarda as suas cópias sob esse marcador. Uma publicação passa, portanto, a ser um conjunto totalmente novo de chaves de cache assim que expira a consulta de 30 segundos da borda. As cópias antigas simplesmente deixam de ser encontradas, por isso a borda pode manter cópias durante um dia sem nunca servir uma que tenha sido substituída pela publicação seguinte.

Os browsers recebem duas regras diferentes:

  • Saída de compilação com hash — ficheiros como assets/index-CzLcxDO8.js, cujo nome muda sempre que o conteúdo muda — fica em cache durante um ano e marcado como imutável. Sob esse nome nunca pode estar desatualizado.
  • Tudo o resto — páginas e ficheiros de nome fixo como um logótipo — é marcado como no-cache, o que significa "verificar antes de usar". Se nada mudou, a resposta é um 304 Not Modified minúsculo, sem corpo, agora que respeitamos a verificação If-None-Match do browser.

Distinguir as duas coisas exige cuidado: um ficheiro copiado de public/assets/ mantém o seu próprio nome, e pôr assets/logo.png em cache durante um ano fixaria o logótipo antigo durante um ano. Por isso, um ficheiro só conta como tendo hash se estiver numa pasta de saída de compilação e o nome tiver um segmento que pareça um hash, e não uma palavra comum.

Localmente, a nova página e o novo logótipo ficaram visíveis 6 segundos depois de a publicação entrar em produção. Antes, eram 60 segundos para a página e um dia para o logótipo.

Duas correções menores pelo caminho

  • Páginas em branco a partir de pedidos HEAD. Um pedido HEAD pede os cabeçalhos de uma página sem o corpo. Estávamos a pôr em cache essas respostas vazias, por isso o visitante seguinte a essa página recebia uma página em branco. As respostas HEAD já não são guardadas em cache.
  • Uma página real para "aqui não há nada". Um endereço sem app recebia antes um texto simples "This published app is offline or the link was not found" com o código de erro 502. Agora recebe uma página adequada, "There's no app here", com o estado 404 e uma forma de voltar ao Mythex para o dono. Domínios personalizados desconhecidos recebem a mesma página.

O que tirámos disto

  • A ordem faz parte da correção. Os mesmos ficheiros enviados por outra ordem são a diferença entre um site partido e um site a funcionar.
  • Apaga tarde, e só o que conheces. Limpar com uma listagem feita antes do envio é seguro; esvaziar uma pasta e esperar que o envio termine não é.
  • Põe em cache por versão, não por tempo. Os tempos de expiração são um palpite sobre quando o conteúdo muda. Uma chave que muda com a compilação é um facto.

Relacionado: a tua app publicada agora continua no ar enquanto a republicas. Mais sobre publicação na documentação.

Mythex · Pricing · Crie qualquer coisa com IA · Modelos de sites e apps · Mythex comparado · Glossário de criação de apps com IA · Ferramentas grátis para criar apps com IA · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)