I siti statici restano online mentre vengono ripubblicati
Ripubblicare un sito statico su Mythex cancellava prima i file online e poi caricava la nuova build, quindi per tutta la durata del caricamento alcuni visitatori ricevevano una pagina 404 oppure una pagina i cui script mancavano. Un caricamento fallito poteva lasciare il sito vuoto o a metà nuovo. Ora la nuova build viene scritta sopra la vecchia, con le pagine per ultime, e i file rimasti vengono rimossi qualche minuto dopo. Una seconda correzione fa sì che una ripubblicazione compaia entro pochi secondi invece che in un minuto, oppure, per file come un logo, fino a un giorno.
Come viene servito un sito statico
Un sito statico è fatto solo di file: pagine HTML, JavaScript, CSS, immagini. Quando lo pubblichi su Mythex, lo costruiamo, carichiamo il risultato in un object storage in una cartella dedicata al tuo sito e lo serviamo tramite una rete edge, cioè server vicini ai visitatori che recuperano i file dallo storage e ne conservano copie per un po'. (Se è una novità per te, la nostra guida su cos'è una CDN spiega l'idea.)
Due cose non andavano: l'ordine in cui una ripubblicazione cambiava i file e per quanto tempo venivano conservate le vecchie copie.
Problema 1: il caricamento svuotava il sito per primo
Una ripubblicazione cancellava tutto nella cartella del sito, poi caricava la nuova build. Per tutta la durata del caricamento (12 secondi per un sito di 250 file nel nostro test locale), un visitatore la cui richiesta non era già in cache sull'edge riceveva un 404, oppure una pagina HTML i cui script restituivano 404.
Un caricamento fallito era peggio. La cartella era già vuota e, su uno dei due percorsi di caricamento, il nuovo index.html poteva arrivare prima del file che era fallito. Una pubblicazione segnalata come fallita poteva lasciare online un sito mezzo nuovo.
La soluzione: scrivi sopra, pagine per ultime, pulizia dopo
- Non cancellare per primo. La nuova build viene caricata sopra quella vecchia.
- Asset prima delle pagine. Una pagina nomina gli script e gli stili di cui ha bisogno, quindi le pagine vanno caricate per ultime. Finché le nuove pagine non sono arrivate, il visitatore riceve la vecchia pagina, che nomina i vecchi asset, ancora presenti. Quando arrivano le nuove pagine, i nuovi asset che nominano sono già al loro posto.
- Rimuovi i residui dopo. Prima del caricamento elenchiamo di cosa è composto il sito. Tre minuti dopo un caricamento riuscito, qualsiasi voce di quell'elenco che la nuova build non ha riscritto viene cancellata. Tre minuti sono più dei 60 secondi per cui una pagina può restare in cache sull'edge e nel browser, quindi un visitatore che ha ancora la vecchia pagina trova gli asset che essa nomina.
- Nel dubbio, non cancellare nulla. Se l'elenco prima del caricamento fallisce, non si rimuove nulla. I file residui sono innocui, e la ripubblicazione successiva li elimina. Cancellare senza sapere cosa c'era è il modo in cui un sito finisce vuoto.
Un caricamento fallito ora lascia il sito precedente esattamente com'era.
Abbiamo testato tutto end to end in locale, usando lo script di caricamento reale, la rotta di caricamento reale e il servizio dello storage, con visitatori che arrivavano con una cache edge fredda. Con il vecchio codice, 55 visite su 91 risultavano rotte durante una ripubblicazione e 61 su 92 durante una ripubblicazione fallita. Con il nuovo codice, 0 sono risultate rotte su circa 3.500 visite che coprivano entrambi i percorsi di caricamento, un caricamento fallito e la pubblicazione successiva, ed è stato rimosso esattamente l'insieme dei file residui.
Problema 2: una ripubblicazione impiegava troppo a comparire
Anche quando il caricamento andava bene, le modifiche comparivano lentamente. L'edge conservava la copia di una pagina per 60 secondi e quella di ogni altro file per un giorno, e lo diceva anche ai browser. I file con un nome fisso, come logo.png, un font o qualsiasi cosa da una cartella public/, potevano mostrare la versione vecchia fino a un giorno dopo una ripubblicazione.
La soluzione: copie dei file sotto un marcatore di build
Quando l'edge chiede alla nostra API dove vive un sito, la risposta ora include un marcatore di build che cambia a ogni pubblicazione. L'edge archivia le sue copie sotto quel marcatore. Una pubblicazione diventa quindi un insieme completamente nuovo di chiavi di cache non appena scade la ricerca di 30 secondi dell'edge. Le vecchie copie non vengono più trovate, quindi l'edge può conservare le copie per un giorno senza mai servire una versione superata dalla pubblicazione che l'ha sostituita.
I browser seguono due regole diverse:
- Output di build con hash: file come
assets/index-CzLcxDO8.js, il cui nome cambia quando cambia il contenuto, vengono messi in cache per un anno e marcati come immutabili. Con quel nome non possono mai diventare obsoleti. - Tutto il resto: pagine e file con nome fisso, come un logo, vengono marcati
no-cache, cioè «verifica prima di usare». Se nulla è cambiato, la risposta è un piccolo304 Not Modifiedsenza corpo, ora che rispettiamo il controlloIf-None-Matchdel browser.
Distinguere i due casi richiede attenzione: un file copiato da public/assets/ mantiene il proprio nome, e mettere in cache per un anno assets/logo.png bloccherebbe per un anno il vecchio logo. Quindi un file conta come «con hash» solo se si trova in una cartella di output della build e il suo nome contiene un segmento che somiglia a un hash, non una parola comune.
In locale, la nuova pagina e il nuovo logo sono risultati visibili 6 secondi dopo che la pubblicazione è andata online. Prima erano 60 secondi per la pagina e un giorno per il logo.
Due correzioni minori emerse strada facendo
- Pagine vuote dalle richieste HEAD. Una richiesta
HEADchiede gli header di una pagina senza il suo corpo. Stavamo mettendo in cache quelle risposte vuote, quindi il visitatore successivo di quella pagina riceveva una pagina bianca. Le risposteHEADnon vengono più messe in cache. - Una pagina vera per «qui non c'è niente». Un indirizzo senza app restituiva un testo semplice «Questa app pubblicata non è disponibile o il link non è stato trovato» con codice di errore 502. Ora riceve una pagina vera, «Non c'è nessuna app qui», con stato 404 e un modo per tornare a Mythex per il proprietario. Anche i domini personalizzati sconosciuti ricevono la stessa pagina.
Cosa ci siamo portati a casa
- L'ordine fa parte della correttezza. Gli stessi file caricati in un ordine diverso fanno la differenza tra un sito rotto e uno funzionante.
- Cancella tardi, e solo ciò che conosci. Rimuovere con un elenco fatto prima del caricamento è sicuro; svuotare una cartella sperando che il caricamento finisca no.
- Metti in cache per versione, non per tempo. I tempi di scadenza sono una stima su quando il contenuto cambia. Una chiave che cambia con la build è un fatto.
Correlato: la tua app pubblicata ora resta online mentre la ripubblichi. Altri dettagli sulla pubblicazione nella documentazione.