Chrome Dev Summit 2018 is happening now and streaming live on YouTube. Watch now.

Ottimizzazione della codifica e delle dimensioni di trasferimento delle risorse di testo

Dopo l'eliminazione dei download non necessari di risorse, la cosa migliore che possiamo fare per migliorare il tempo di carimanento della pagina è minimizzare la dimensione da scaricare mediante ottimizzazione e compressione delle rimanenti risorse.

Introduzione alla compressione dei dati

Una volta eliminate tutte le risorse non necessarie, è necessario minimizzare le dimensioni totali delle risorse restanti che il browser deve scaricare, ovvero comprimerle. A seconda del tipo di risorsa—testo, immagine, font e così via—abbiamo diverse tecniche a nostra disposizione: strumenti generici che possono essere abilitati sul server, procedure di ottimizzazione pre-elaborazione per tipi di contenuto specifici o per specifiche risorse, che richiedono l'intervento del developer.

Per garantire le prestazioni migliori, è necessaria una combinazione delle diverse tecniche.

TL;DR

  • La compressione è una procedura di codifica delle informazioni che utilizza un numero inferiore di bit
  • L'eliminazione dei dati non necessari consente sempre di raggiungere i risultati migliori
  • Esistono numerose tecniche e algoritmi di compressione diversi
  • Per ottenere la compressione ottimale, dovrai avvalerti di più tecniche

La procedura di riduzione delle dimensioni dei dati, nota come compressione dei dati. Molte persone hanno contribuito ad algoritmi, tecniche e procedure di ottimizzazione per migliorare le percentuali, la velocità di compressione ed i requisiti di memoria dei diversi compressori. Inutile dire che una discussione approfondita su tale argomento esula dal nostro ambito. Tuttavia è comunque importante comprendere ad alto livello come funziona la compressione e le tecniche che abbiamo a disposizione per ridurre le dimensioni di diverse risorse presenti nelle nostre pagine.

Per illustrare i principi chiave di tali tecniche, consideriamo il processo di ottimizzazione di un semplice messaggio di testo inventato come esempio:

# Il seguente è un messaggio segreto, composto da un gruppo di intestazioni
# in formato chiave-valore seguito da un ritorno a capo e dal messaggio
# cifrato.
format: secret-cipher
date: 25/08/16
AAAZZBBBBEEEMMM EEETTTAAA
  1. I messaggi possono contenere annotazioni di vario tipo, indicate dal prefisso "#". Le annotazioni non influenzano né il significato, né alcun altro aspetto del messaggio.
  2. I messaggi possono contenere delle intestazioni composte da coppie di chiave-valore (separate da ":") che compaiono all'inizio del messaggio.
  3. I messaggi contengono payload testuale.

Come potremmo ridurre le dimensioni del messaggio precedente, attualmente di 200 caratteri?

  1. Il commento è interessante, ma sappiamo che non influenza di fatto il significato del messaggio. Per cui lo elimineremo nella trasmissione dello stesso.
  2. Vi sono probabilmente alcune tecniche intelligenti che possiamo utilizzare per codificare le intestazioni in modo efficace. Ad esempio, se sappiamo che tutti i messaggi contengono un "format" e un "date", possiamo convertirli in ID interi brevi e inviare solo quelli. Detto ciò, non siamo sicuri che sia questo il caso, per cui lo lasceremo in sospeso per adesso.
  3. Il payload è formato da solo testo, e, anche se non sappiamo quale sia il suo reale contenuto (apparentemente, utilizza un "messaggio segreto"), solo osservando il testo sembra che vi sia una notevole ridondanza. Forse, invece di mandare lettere ripetute, possiamo semplicemente contare il numero di esse e codificarle in maniera più efficace? Per esempio "AAA" diventa "3A" che rappresenta una sequenza di tre A.

Mettendo assieme le diverse tecniche, arriviamo al risultato seguente:

format: secret-cipher
date: 25/08/16
3A2Z4B3E3M 3E3T3A

Il nuovo messaggio è lungo 56 caratteri, il che significa che siamo riusciti a comprimere il messaggio originale di un sorprendente 72%.

Naturalmente, ti chiederai, tutto ciò è fantastico, ma come può aiutarci ad ottimizzare le nostre pagine web? Sicuramente non inventeremo degli algoritmi di compressione, ma come vedrai, utilizzeremo esattamente le stesse tecniche e processi mentali quando ottimizzeremo le diverse risorse sulle nostre pagine: pre-elaborazione, ottimizzazione specifica per il contesto e algoritmi specifici per contenuti diversi.

Minificazione: pre-elaborazione e ottimizzazione specifica per il contesto

TL;DR

  • Un'ottimizzazione specifica in base ai contenuti può ridurre considerevolmente le dimensioni delle risorse offerte.
  • Un'ottimizzazione specifica in base ai contenuti si applica meglio nel ciclo di build/release.

Il modo migliore per comprimere dati ridondanti o non necessari consiste nell'eliminarli in un'unica soluzione. Naturalmente, non possiamo semplicemente eliminare dei dati a caso, ma in alcuni contesti in cui disponiamo di una conoscenza specifica del contenuto dei dati e delle relative proprietà, è spesso possibile ridurre significativamente le dimensioni del payload senza inficiarne il significato.

<html>
  <head>
  <style>
     /* awesome-container is only used on the landing page */
     .awesome-container { font-size: 120% }
     .awesome-container { width: 50% }
  </style>
 </head>

 <body>
   <!-- awesome container content: START -->
    <div>…</div>
   <!-- awesome container content: END -->
   <script>
     awesomeAnalytics(); // beacon conversion metrics
   </script>
 </body>
</html>

Prova

Considera la semplice pagina HTML precedente e i suoi tre diversi tipi di contenuto: markup HTML, stili CSS e JavaScript. Ciascun tipo di contenuto dispone di norme diverse per quanto riguarda ciò che rappresenta un contenuto valido, differenti regole per indicare commenti, ecc. Come possiamo ridurre le dimensioni di questa pagina?

  • I commenti all'interno del codice sono i migliori amici di un developer, ma il browser non deve vederli! La semplice eliminazione dei commenti CSS (/* ... */), HTML (<!-- ... -->) e JavaScript (// ...) può ridurre significativamente le dimensioni totali della pagina.
  • Un compressore CSS "intelligente" potrebbe notare che stiamo utilizzando un metodo inefficace di definizione di regole per ".awesome-container" ed accorpare i due periodi in uno senza influenzare altri stili, risparmiando altri byte.
  • Gli spazi vuoti (semplici spazi e tab) sono utilizzati per comodità dai developer in HTML, CSS e JavaScript. Un ulteriore compressore potrebbe eliminare tutti i tab e gli spazi.
<html><head><style>.awesome-container{font-size:120%;width: 50%}
</style></head><body><div>…</div><script>awesomeAnalytics();
</script></body></html>

Prova

Una volta applicate tali passi, la nostra pagina passerà da 406 a 150 caratteri, riducendosi del 63%! Molto probabilmente non sarà molto leggibile, ma d'altronde non deve neanche esserlo: possiamo mantenere la pagina originale come "development version" e poi applicare le procedure precedenti quando saremo pronti a inserire la pagina sul nostro sito web.

Facendo un passo indietro, l'esempio precedente illustra un punto importante: anche un compressore generico—diciamo ideato per comprimere un qualsiasi testo— potrebbe svolgere un buon lavoro per comprimere la pagina precedente, ma non saprebbe certo come eliminare i commenti, raggruppare le regole CSS o effettuare dozzine di altre procedure di ottimizzazione specifiche. Ecco perché pre-elaborazione/minificazione/ottimizzazione basata sul contesto possono rivelarsi strumenti molto potenti.

Allo stesso modo, le tecniche precedenti possono essere estese a risorse non basate sul solo testo. Immagini, video e altri tipi di contenuti contengono tutti i propri metadati e diversi payload. Ad esempio, ogni volta che scatti una foto con la tua fotocamera, la foto contiene di norma numerose informazioni extra: le impostazioni della fotocamera, il luogo, ecc... A seconda della tua applicazione, tali dati possono essere fondamentali (ad es. il sito di condivisione della foto) o perfettamente inutili; dovrai quindi valutare se valga la pena rimuoverli. In pratica, tali metadati possono aggiungere decine di kilobyte per ogni immagine.

In breve, come primo passo nell'ottimizzazione dell'efficienza delle nostre risorse, crea un inventario dei diversi tipi di contenuti e valuta quali tipi di ottimizzazioni specifiche puoi applicare per ridurne le dimensioni; potrai così ottenere risultati significativi! Poi, una volta definito ciò, automatizza tali ottimizzazioni aggiungendole alle procedure build e release; per garantire che vengano sempre effettuate.

Compressione del testo con GZIP

TL;DR

  • GZIP funziona meglio su risorse di testo: CSS, JavaScript, HTML.
  • Tutti i browser moderni supportano la compressione con GZIP e la richiedono automaticamente
  • Il tuo server deve essere configurato con la compressione GZIP abilitata
  • Molti CDN richiedono particolare attenzione per assicurarsi che GZIP sia abilitata

GZIP è un compressore generico applicabile a qualsiasi stream di byte. Sotto il cofano, ricorda alcuni contenuti visti in precedenza e cerca di individuare e sostituire i frammenti di dati duplicati in maniera efficace. (Se sei curioso, ecco una spiegazione a basso livello di GZIP.) Tuttavia, in pratica, GZIP funziona meglio su risorse di testo, raggiungendo spesso un tasso di compressione del 70-90% per i file più grossi, mentre su risorse già compresse tramite algoritmi alternativi (ad es. la maggior parte dei formati immagine) consente di avere qualche piccolo se non nessun miglioramento.

Tutti gli attuali browser supportano ed negoziano automaticamente la compressione GZIP per ogni richiesta HTTP. Devi solo assicurarti che il server sia configurato correttamente per fornire la risorsa compressa quando il client la richiede.

Libreria Dimensioni Dimensioni compresse Percentuale di compressione
jquery-1.11.0.js 276 KB 82 KB 70%
jquery-1.11.0.min.js 94 KB 33 KB 65%
angular-1.2.15.js 729 KB 182 KB 75%
angular-1.2.15.min.js 101 KB 37 KB 63%
bootstrap-3.1.1.css 118 KB 18 KB 85%
bootstrap-3.1.1.min.css 98 KB 17 KB 83%
foundation-5.css 186 KB 22 KB 88%
foundation-5.min.css 146 KB 18 KB 88%

La tabella precedente illustra il risparmio consentito dalla compressione con GZIP per alcune delle librerie JavaScript e dei framework CSS più noti. Il risparmio va dal 60 all'88%; nota come la combinazione tra file minificati (identificati con “.min” nel nome) più GZIP offra una riduzione ancora maggiore.

  1. Applica prima le ottimizzazioni specifiche per i contenuti: minificatori CSS, JS e HTML.
  2. Applica GZIP per comprimere il risultato minificato.

L'attivazione di GZIP rappresenta una delle ottimizzazioni più semplici ed efficaci da applicare; sfortunatamente, molte persone si dimenticano ancora di farlo. La maggior parte dei server web comprime i contenuti per nostro conto, e resta solo da verificare che il server sia configurato correttamente per comprimere tutti i contenuti che possano beneficiare della compressione con GZIP.

Il progetto HTML5 Boilerplate contiene alcuni file di configurazione di esempio per tutti i principali server, con commenti dettagliati per ogni flag e impostazione di configurazione. Per determinare la configurazione migliore per il tuo server segui i seguenti passi: Cerca il tuo server preferito nell'elenco. Vai alla sezione GZIP. * Assicurati che il tuo server sia configurato secondo le impostazioni raccomandate.

Demo DevTools confronto dimensioni reali vs.
trasferite

Un modo semplice e rapido di vedere GZIP in azione consiste nell'aprire Chrome DevTools e controllare la colonna “Size / Content“ nella scheda Rete: “Size“ indica le dimensioni di trasferimento della risorsa, mentre “Content“ indica le dimensioni espanse della risorsa. Per la risorsa HTML dell'esempio precedente, GZIP ha risparmiato 98.8 KB durante il trasferimento!

Infine, nonostante la maggior parte dei server comprime automaticamente le risorse al posto tuo prima di presentarle all'utente, alcuni CDN richiedono particolare attenzione e un'azione manuale per garantire che gli oggetti GZIP siano serviti. Verifica che le risorse presenti sul tuo sito siano effettivamente compresse