Data di pubblicazione: 6 marzo 2024
La compressione dei dati è una tecnica di ottimizzazione del rendimento collaudata nel tempo che riduce le dimensioni delle risorse della pagina idonee. Per un po' di tempo, è stata una pratica comune utilizzare principalmente gzip sui server web per comprimere le risorse della pagina comuni basate su testo, come i file HTML, CSS e JavaScript, e inviarle al client dove potevano essere decompresse. Il risultato è un caricamento più rapido delle risorse senza influire sul comportamento previsto di una pagina.
Sebbene gzip sia di per sé molto efficace, negli ultimi anni sono stati realizzati ulteriori miglioramenti nella compressione sul web. Nel 2016, l'algoritmo Brotli è stato distribuito in Chrome, offrendo rapporti di compressione complessivamente migliori per le risorse idonee. Entro la fine del 2017, tutti i browser moderni supportavano Brotli e il supporto del server per questo algoritmo ha iniziato a diffondersi. Più di recente, Chrome ha distribuito la compressione ZStandard.
Ma il lavoro non finisce qui. Il team di Chrome ha lavorato per rendere utilizzabili sul web i dizionari condivisi, che ora sono disponibili in una prova dell'origine sia per Brotli sia per ZStandard. I dizionari condivisi possono integrare la compressione Brotli e ZStandard per offrire rapporti di compressione notevolmente più elevati per i siti web che spesso distribuiscono codice aggiornato e, in alcuni casi, possono offrire rapporti di compressione pari o superiori al 90%. Questo post fornisce maggiori dettagli su come funzionano i dizionari condivisi e su come registrarti alle prove dell'origine per utilizzarli per Brotli e ZStandard sul tuo sito web. Puoi anche dare un'occhiata a questo video:
Spiegazione dei dizionari condivisi
La compressione è un processo che consiste nel trovare sequenze ridondanti in un input e utilizzare queste informazioni per creare un output molto più piccolo, che può essere invertito in un secondo momento. La compressione funziona bene sul web perché riduce notevolmente i tempi di caricamento delle risorse. Sia Brotli sia ZStandard possono aumentare ulteriormente la loro efficacia utilizzando un dizionario di compressione, ovvero una raccolta di pattern aggiuntivi che questi algoritmi possono utilizzare durante la compressione. Infatti, l'elevata efficienza di Brotli è ottenuta in una certa misura utilizzando un dizionario interno.
Tuttavia, con Brotli e ZStandard è possibile utilizzare dizionari personalizzati curati dall'utente che contengono pattern specifici per determinate risorse. In pratica, un dizionario personalizzato è un file esterno che può essere applicato a qualsiasi input. I dizionari possono essere molto specifici per il codice di produzione di un'applicazione o per qualsiasi contenuto. L'applicabilità di un determinato dizionario al suo input può avere un impatto significativo sull'efficienza complessiva della compressione. I dizionari molto simili ai contenuti di un input produrranno output con rapporti di compressione più elevati rispetto ai dizionari con contenuti generici o diversi.
Ecco un esempio di quanto può essere efficace un dizionario di compressione personalizzato: supponiamo che il tuo sito web utilizzi il framework Angular e che la versione corrente che stai utilizzando sia la 1.7.9. Questa versione del framework Angular è di circa 172 KiB non compressi. Se compressa con le impostazioni predefinite di Brotli, le sue dimensioni diventano di circa 53 KiB. Questo produce un rapporto di compressione di quasi il 70%. Tuttavia, supponiamo che tu decida di eseguire l'upgrade ad Angular 1.8.3 in un secondo momento. Poiché questa versione di Angular ha all'incirca le stesse dimensioni della versione 1.7.9, puoi aspettarti un rapporto di compressione pressoché identico a quello della versione precedente.
È qui che un dizionario personalizzato può essere utile utilizzando un processo noto come compressione delta , ovvero quando è possibile utilizzare un dizionario di una versione precedente di una risorsa per comprimere una versione successiva. Utilizzando l'esempio precedente, se comprimi la versione 1.8.3 di Angular utilizzando la versione 1.7.9 come dizionario, l'output sarà di poco più di 4 KiB. Questo rappresenta un rapporto di compressione di quasi il 98%. È chiaro che i dizionari di compressione possono avere un impatto significativo sul rendimento del caricamento e la loro efficacia è già stata realizzata in applicazioni reali!
Tuttavia, è difficile far funzionare questo flusso sul web. Il problema è che, se utilizzi un dizionario per comprimere una risorsa, devi avere lo stesso dizionario per decomprimerla. Questo flusso è già stato tentato sul web, in particolare con SDCH, ma è stato difficile da implementare in modo sicuro. Questa ultima proposta per la compressione dei dizionari condivisi risolve questi problemi e offre un vantaggio sostanziale sia per le risorse statiche sia per quelle dinamiche.
In che modo Chrome pubblicizza il supporto per i dizionari condivisi
Tutti i browser pubblicizzano gli algoritmi di compressione che supportano tramite l'intestazione della richiesta Accept-Encoding. Il contenuto dell'intestazione è un elenco separato da virgole di codifiche supportate:
Accept-Encoding: gzip, br, zstd
Questa particolare intestazione Accept-Encoding indica che il browser che richiede la risorsa supporta gli algoritmi di compressione gzip, Brotli e ZStandard. Un server web che risponde alla richiesta può quindi decidere quale algoritmo utilizzare quando risponde alla richiesta.
Quando il supporto per i dizionari condivisi è attivato e per una risorsa è disponibile un dizionario pertinente, all'intestazione Accept-Encoding vengono aggiunti token aggiuntivi. Questi token sono br-d per Brotli e zstd-d per Zstandard. Chrome includerà anche l'hash di un dizionario disponibile, che verrà trattato di seguito.
Accept-Encoding: gzip, br, zstd, br-d, zstd-d
Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:
Se un server web è configurato per riconoscere questo token e riconosce il dizionario, può rispondere alla richiesta con una risorsa compressa utilizzando il dizionario per la codifica applicabile. Il modo in cui ciò viene ottenuto in pratica dipende dal fatto che la richiesta sia per una risorsa statica o dinamica.
Compressione dei dizionari condivisi per le risorse statiche
Una risorsa di pagina statica è una risorsa che produce sempre la stessa risposta per un URL richiesto. Esempi comuni di risorse di pagina statiche comprimibili sono i file JavaScript e CSS. Queste risorse sono in genere versionate in qualche modo per la memorizzazione nella cache, a volte con un hash dei contenuti del file nel nome file (ad esempio styles.abcd1234.css) o con un altro metodo di fingerprinting della risorsa. Questi tipi di risorse sono un ottimo candidato per la compressione delta fornita dai dizionari condivisi, poiché le risorse statiche vengono spesso memorizzate nella cache per lunghi periodi di tempo e tendono a essere aggiornate con una certa frequenza.
È possibile specificare un dizionario per una risorsa statica impostando l'intestazione della risposta Use-As-Dictionary. L'intestazione accetta una delle coppie chiave-valore, ma l'unica obbligatoria è match, che accetta la sintassi URLPattern che specifica il percorso della risorsa in cui deve essere utilizzato il dizionario:
Use-As-Dictionary: match="/dist/styles.*.css"
Considera l'intestazione Use-As-Dictionary come un meccanismo che si applica alle versioni future di una risorsa che corrispondono al pattern specificato al suo interno. Supponiamo che il tuo sito web distribuisca tutti i suoi stili in un unico file CSS. Per semplicità, supponiamo che la prima versione della risorsa si trovi all'indirizzo /dist/styles.v1.css e venga inviata con un'intestazione della risposta Use-As-Dictionary contenente un valore match di /dist/styles.*.css.
Dopo un po' di tempo, aggiorni il CSS del tuo sito web e ne distribuisci una nuova versione all'indirizzo /dist/styles.v2.css. Poiché il valore match utilizzato nell'intestazione della risposta Use-As-Dictionary della versione precedente si applica a questa richiesta, il browser invierà un'intestazione Available-Dictionary contenente un hash del dizionario codificato come una sequenza di byte di campo strutturato:
Accept-Encoding: gzip, br, zstd, br-d, zstd-d
Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:
A questo punto, spetta al server configurare la compressione per assicurarsi che venga utilizzato il dizionario corrispondente. La risorsa compressa con questo dizionario verrà quindi inviata e il dizionario disponibile nella cache del browser dell'utente verrà utilizzato per decomprimerla.
Se distribuisci spesso nuovo codice per il tuo sito web, la compressione delta può essere molto utile. Tuttavia, la procedura è flessibile. Se il browser non determina che un dizionario è disponibile nella cache del browser dell'utente, non specificherà i token br-d o zstd-d aggiuntivi nell'intestazione Accept-Encoding. In questo caso, si applica il flusso di compressione standard.
Compressione dei dizionari condivisi per le risorse dinamiche
Anche le risorse dinamiche possono trarre vantaggio dalla compressione dei dizionari condivisi. Le risorse dinamiche sono quelle che cambiano in base a un contesto, ad esempio un sito web di notizie in cui la pagina principale viene aggiornata di frequente quando vengono pubblicate nuove notizie. I documenti HTML sono spesso risorse dinamiche. In questi casi, il dizionario può contenere la maggior parte della struttura HTML comune del sito e il codice del modello, il che porta a pagine compresse in cui vengono inviate solo le parti univoche di ogni pagina.
A causa della natura delle risorse generate dinamicamente, un dizionario deve essere caricato sul client per un utilizzo successivo. Il caricamento anticipato di un dizionario significa che l'applicazione della compressione dei dizionari condivisi alle risorse dinamiche è speculativa. In questi casi, si spera che il tuo sito web riceva traffico sufficiente da ammortizzare il costo del dizionario su un numero elevato di navigazioni. Se decidi di provarlo, il primo passo è specificare la posizione del dizionario tramite un elemento <link> nell'HTML della pagina:
<link rel="dictionary" href="/dictionary.dat">
Quando Chrome rileva questo elemento <link>, potrebbe recuperare il dizionario una volta che la pagina è inattiva e con priorità bassa per evitare la contesa della larghezza di banda. La risposta per il dizionario stesso deve specificare un'intestazione Use-As-Dictionary e il percorso della risorsa dinamica a cui si applica:
Use-As-Dictionary: match="/product/*"
Da qui, il flusso è in gran parte lo stesso delle risorse statiche. Il browser vedrà che il dizionario stesso si applica alle risorse corrispondenti e aggiungerà un'intestazione Available-Dictionary alla richiesta con un hash dei contenuti del dizionario, in modo simile al flusso delle risorse statiche spiegato in precedenza.
Comprimere le risorse statiche in fase di compilazione
Se hai familiarità con i bundler, potresti conoscere vari plug-in che possono comprimere le risorse in fase di compilazione e successivamente pubblicare queste risorse compresse. Ad esempio, Apache ti consente di utilizzare le direttive per pubblicare queste risorse precompresse al momento della richiesta.
La maggior parte dei bundler basati su Node.js che supportano la compressione utilizza la libreria Zlib integrata di Node. Zlib offre il supporto per Brotli e i bundler che lo utilizzano in genere offrono un'interfaccia per passare le opzioni direttamente a Zlib, che supporta la compressione assistita dal dizionario. Ecco alcuni bundler che supportano l'utilizzo dei dizionari:
CompressionWebpackPlugindi webpack, tramite l'interfacciacompressionOptions.rollup-plugin-brotlioffre una configurazioneoptionsche passa direttamente a Zlib in Node.js, dove è possibile specificare i dizionari.- Anche il plug-in di terze parti
esbuild-plugin-compressper esbuild offre l'accesso alle opzioni Zlib in Node.js.
Tieni presente che i dizionari disponibili per una determinata versione di una risorsa possono utilizzare una delle versioni precedenti della risorsa. Ciò significa che dovrai analizzare il traffico degli utenti e pianificare di conseguenza. Cerca un equilibrio e genera risorse che avvantaggino il maggior numero possibile di utenti di ritorno. I provider CDN stanno attualmente sperimentando la compressione dei dizionari condivisi. Al momento non sono disponibili implementazioni per l'uso pubblico, ma prevediamo che questa situazione cambierà.
Prova
L'integrazione della compressione dei dizionari condivisi con le funzionalità di compressione esistenti del browser ha il potenziale per migliorare notevolmente il rendimento del caricamento dei siti web che distribuiscono spesso codice di produzione aggiornato e ricevono un traffico significativo da visitatori di ritorno. Se ti interessa provare la compressione dei dizionari condivisi, hai due opzioni:
- Se vuoi solo sperimentare la compressione dei dizionari condivisi per capire come funziona, puoi attivare la funzionalità sperimentale Trasporto del dizionario di compressione nella pagina
chrome://flags. - Se ti interessa provare questa funzionalità sul tuo sito web di produzione e vedere come la compressione dei dizionari condivisi potrebbe avvantaggiare gli utenti reali, registrati alla prova dell'origine per ottenere un token e leggi come funzionano le prove dell'origine.
Conclusione
Siamo molto entusiasti di questo importante progresso nella tecnologia di compressione sul web e di quanto potrebbe velocizzare le applicazioni esistenti che le persone utilizzano ogni giorno. Ti invitiamo a provarla e, soprattutto, ci piacerebbe conoscere la tua opinione. Se trovi un bug, segnalalo all'indirizzo crbug.com. Per ulteriori risorse e strumenti, visita use-as-dictionary.com. Infine, se ti interessa approfondire il funzionamento, la spiegazione è un buon passo successivo.