Fornire applicazioni veloci e leggere con Save-Data

Dave Gash
Dave Gash
Ilya Grigorik
Ilya Grigorik

L'intestazione della richiesta client hint Save-Data disponibile nei browser Chrome, Opera e Yandex consente agli sviluppatori di fornire applicazioni più leggere e veloci agli utenti che attivano la modalità di risparmio dati nel browser.

La necessità di pagine leggere

Statistiche di Web Light

Tutti concordano sul fatto che le pagine web più veloci e leggere offrono un'esperienza utente più soddisfacente, consentono una migliore comprensione e memorizzazione dei contenuti e generano un aumento delle conversioni e delle entrate. Le ricerche di Google hanno dimostrato che "…le pagine ottimizzate vengono caricate quattro volte più velocemente rispetto alla pagina originale e con l'80% di byte in meno. Dato che il caricamento avviene molto più velocemente, abbiamo riscontrato il 50% in più di traffico verso queste pagine."

Inoltre, sebbene il numero di connessioni 2G sia finalmente in calo, il 2G era ancora la tecnologia di rete dominante nel 2015. La penetrazione e la disponibilità delle reti 3G e 4G stanno crescendo rapidamente, ma i costi di proprietà associati e i vincoli di rete sono ancora un fattore significativo per centinaia di milioni di utenti.

Questi sono argomenti validi a favore dell'ottimizzazione delle pagine.

Esistono metodi alternativi per migliorare la velocità del sito senza il coinvolgimento diretto degli sviluppatori, come i browser proxy e i servizi di transcodifica. Sebbene questi servizi siano piuttosto popolari, presentano svantaggi significativi: compressione semplice (e talvolta inaccettabile) di immagini e testo, incapacità di elaborare pagine sicure (HTTPS), ottimizzazione solo delle pagine visitate tramite un risultato di ricerca e altro ancora. La popolarità stessa di questi servizi è un indicatore del fatto che gli sviluppatori web non stanno rispondendo adeguatamente all'elevata domanda degli utenti di applicazioni e pagine veloci e leggere. Ma raggiungere questo obiettivo è un percorso complesso e a volte difficile.

L'intestazione della richiesta Save-Data

Una tecnica abbastanza semplice consiste nel lasciare che sia il browser ad aiutare, utilizzando l'intestazione della richiesta Save-Data. Identificando questa intestazione, una pagina web può personalizzare e offrire un'esperienza utente ottimizzata agli utenti con vincoli di costi e prestazioni.

I browser supportati (di seguito) consentono all'utente di attivare una *modalità Risparmio dati* che autorizza il browser ad applicare un insieme di ottimizzazioni per ridurre la quantità di dati necessari per il rendering della pagina. Quando questa funzionalità viene esposta o pubblicizzata, il browser potrebbe richiedere immagini a risoluzione inferiore, posticipare il caricamento di alcune risorse o instradare le richieste tramite un servizio che applica altre ottimizzazioni specifiche per i contenuti, come la compressione delle risorse di immagini e testo.

Supporto browser

  • Chrome 49 e versioni successive pubblicizza Save-Data quando l'utente attiva l'opzione "Risparmio dati" sui dispositivi mobili o l'estensione "Risparmio dati" sui browser desktop.
  • Opera 35 e versioni successive pubblicizza Save-Data quando l'utente attiva la modalità "Opera Turbo" su computer o l'opzione "Risparmio dati" sui browser Android.
  • Yandex 16.2+ annuncia Save-Data quando la modalità Turbo è attiva su browser desktop o mobile.

Rilevamento dell'impostazione Save-Data

Per determinare quando offrire l'esperienza "light" agli utenti, l'applicazione può verificare l'intestazione della richiesta dei client hint Save-Data. Questa intestazione della richiesta indica la preferenza del client per un utilizzo ridotto dei dati a causa di costi di trasferimento elevati, velocità di connessione ridotte o altri motivi.

Quando l'utente attiva la modalità di risparmio dati nel browser, quest'ultimo aggiunge l'intestazione della richiesta Save-Data a tutte le richieste in uscita (sia HTTP che HTTPS). Al momento della stesura di questo articolo, il browser annuncia un solo token *on nell'intestazione (Save-Data: on), ma questo potrebbe essere esteso in futuro per indicare altre preferenze dell'utente.

Inoltre, è possibile rilevare se Save-Data è attivato in JavaScript:

if ('connection' in navigator) {
  if (navigator.connection.saveData === true) {
    // Implement data saving operations here.
  }
}

Verificare la presenza dell'oggetto connection all'interno dell'oggetto navigator è fondamentale, in quanto rappresenta l'API Network Information, implementata solo nei browser internet Chrome, Chrome per Android e Samsung Internet. Da lì, devi solo verificare se navigator.connection.saveData è uguale a true e puoi implementare qualsiasi operazione di salvataggio dei dati in questa condizione.

L'intestazione Save-Data mostrata negli Strumenti per sviluppatori di Chrome insieme all'estensione Risparmio dati.
Attivazione dell'estensione Risparmio dati in Chrome per computer.

Se la tua applicazione utilizza un service worker, può ispezionare le intestazioni della richiesta e applicare la logica pertinente per ottimizzare l'esperienza. In alternativa, il server può cercare le preferenze pubblicizzate nell'intestazione della richiesta Save-Data e restituire una risposta alternativa, ad esempio un markup diverso, immagini e video più piccoli e così via.

Suggerimenti e best practice per l'implementazione

  1. Quando utilizzi Save-Data, fornisci alcuni dispositivi UI che lo supportano e consenti agli utenti di passare facilmente da un'esperienza all'altra. Ad esempio:
    • Informa gli utenti che Save-Data è supportato e incoraggiali a utilizzarlo.
    • Consenti agli utenti di identificare e scegliere la modalità con prompt appropriati e pulsanti di attivazione/disattivazione o caselle di controllo intuitivi.
    • Quando è selezionata la modalità di risparmio dati, annuncia e fornisci un modo semplice ed evidente per disattivarla e tornare all'esperienza completa, se l'utente lo desidera.
  2. Ricorda che le applicazioni leggere non sono applicazioni di qualità inferiore. Non omettono funzionalità o dati importanti, ma sono semplicemente più consapevoli dei costi coinvolti e dell'esperienza utente. Ad esempio:
    • Un'applicazione di galleria fotografica potrebbe fornire anteprime a risoluzione inferiore o utilizzare un meccanismo di carosello con meno codice.
    • Un'applicazione di ricerca potrebbe restituire meno risultati alla volta, limitare il numero di risultati con molti contenuti multimediali o ridurre il numero di dipendenze necessarie per eseguire il rendering della pagina.
    • Un sito di notizie potrebbe mostrare meno notizie, omettere le categorie meno popolari o fornire anteprime multimediali più piccole.
  3. Fornisci la logica del server per verificare la presenza dell'intestazione della richiesta Save-Data e valuta la possibilità di fornire una risposta di pagina alternativa e più leggera quando è abilitata, ad esempio riduci il numero di risorse e dipendenze richieste, applica una compressione delle risorse più aggressiva e così via.
    • Se pubblichi una risposta alternativa basata sull'intestazione Save-Data, ricordati di aggiungerla all'elenco Vary (Vary: Save-Data) per indicare alle cache upstream che devono memorizzare nella cache e pubblicare questa versione solo se è presente l'intestazione della richiesta Save-Data. Per maggiori dettagli, consulta le best practice per l'interazione con le cache.
  4. Se utilizzi un service worker, la tua applicazione può rilevare quando l'opzione di risparmio dati è attiva controllando la presenza dell'intestazione della richiesta Save-Data o controllando il valore della proprietà navigator.connection.saveData. Se l'opzione è attiva, valuta se puoi riscrivere la richiesta per recuperare meno byte o utilizzare una risposta già recuperata.
  5. Valuta la possibilità di integrare Save-Data con altri indicatori, ad esempio informazioni sul tipo di connessione e sulla tecnologia dell'utente (consulta l'API NetInfo). Ad esempio, potresti voler offrire l'esperienza leggera a qualsiasi utente con una connessione 2G anche se Save-Data non è abilitato. Al contrario, il fatto che l'utente utilizzi una connessione 4G "veloce" non significa che non sia interessato a risparmiare dati, ad esempio quando è in roaming. Inoltre, puoi aumentare la presenza di Save-Data con l'hint client Device-Memory per adattarti ulteriormente agli utenti su dispositivi con memoria limitata. La memoria del dispositivo dell'utente viene pubblicizzata anche nel suggerimento client navigator.deviceMemory.

Ricette

Ciò che puoi ottenere tramite Save-Data è limitato solo dalla tua immaginazione. Per darti un'idea di ciò che è possibile fare, esaminiamo un paio di casi d'uso. Durante la lettura, potresti pensare ad altri casi d'uso, quindi non esitare a sperimentare e vedere cosa è possibile fare.

Sto cercando Save-Data nel codice lato server

Sebbene lo stato Save-Data possa essere rilevato in JavaScript tramite la proprietà navigator.connection.saveData, a volte è preferibile rilevarlo lato server. In alcuni casi, l'esecuzione di JavaScript può non riuscire. Inoltre, il rilevamento lato server è l'unico modo per modificare il markup prima che venga inviato al client, il che è coinvolto in alcuni dei casi d'uso più vantaggiosi di Save-Data.

La sintassi specifica per rilevare l'intestazione Save-Data nel codice lato server dipende dal linguaggio utilizzato, ma l'idea di base dovrebbe essere la stessa per qualsiasi backend dell'applicazione. In PHP, ad esempio, le intestazioni della richiesta vengono archiviate nell'array superglobale $_SERVER in indici che iniziano con HTTP_. Ciò significa che puoi rilevare l'intestazione Save-Data controllando l'esistenza e il valore della variabile $_SERVER["HTTP_SAVE_DATA"] in questo modo:

// false by default.
$saveData = false;

// Check if the `Save-Data` header exists and is set to a value of "on".
if (isset($_SERVER["HTTP_SAVE_DATA"]) && strtolower($_SERVER["HTTP_SAVE_DATA"]) === "on") {
  // `Save-Data` detected!
  $saveData = true;
}

Se inserisci questo controllo prima che qualsiasi markup venga inviato al client, la variabile $saveData conterrà lo stato Save-Data e sarà disponibile ovunque per l'utilizzo nella pagina. Ora che abbiamo illustrato questo meccanismo, vediamo alcuni esempi di come possiamo utilizzarlo per limitare la quantità di dati che inviamo all'utente.

Pubblica immagini a bassa risoluzione per schermi ad alta risoluzione

Un caso d'uso comune per le immagini sul web prevede la pubblicazione di immagini in gruppi di due: un'immagine per gli schermi "standard" (1x) e un'altra immagine di dimensioni doppie (2x) per gli schermi ad alta risoluzione (ad es. Retina Display). Questa classe di schermi ad alta risoluzione non è necessariamente limitata ai dispositivi di fascia alta e sta diventando sempre più comune. Nei casi in cui è preferibile un'esperienza con l'applicazione più leggera, potrebbe essere prudente inviare immagini a risoluzione inferiore (1x) a questi schermi, anziché varianti più grandi (2x). Per ottenere questo risultato quando è presente l'intestazione Save-Data, modifichiamo semplicemente il markup che inviamo al client:

if ($saveData === true) {
  // Send a low-resolution version of the image for clients specifying `Save-Data`.
  ?><img src="butterfly-1x.jpg" alt="A butterfly perched on a flower."><?php
}
else {
  // Send the usual assets for everyone else.
  ?><img src="butterfly-1x.jpg" srcset="butterfly-2x.jpg 2x, butterfly-1x.jpg 1x" alt="A butterfly perched on a flower."><?php
}

Questo caso d'uso è un esempio perfetto di quanto sia facile soddisfare le richieste di un utente che ti chiede espressamente di inviargli meno dati. Se non ti piace modificare il markup nel backend, puoi ottenere lo stesso risultato utilizzando un modulo di riscrittura degli URL come mod_rewrite di Apache. Esistono esempi di come ottenere questo risultato con una configurazione relativamente ridotta.

Puoi anche estendere questo concetto alle proprietà CSS background-image aggiungendo semplicemente una classe all'elemento <html>:

<html class="<?php if ($saveData === true): ?>save-data<?php endif; ?>">

Da qui, puoi scegliere come target la classe save-data sull'elemento <html> nel tuo CSS per modificare il modo in cui vengono pubblicate le immagini. Potresti inviare immagini di sfondo a bassa risoluzione a schermi ad alta risoluzione, come mostrato nell'esempio HTML riportato sopra, oppure omettere del tutto determinate risorse.

Ometti le immagini non essenziali

Alcuni contenuti delle immagini sul web non sono semplicemente essenziali. Sebbene queste immagini possano essere utili per i contenuti, potrebbero non essere gradite da chi cerca di sfruttare al massimo i piani dati a consumo. In quello che è forse il caso d'uso più semplice di Save-Data, possiamo utilizzare il codice di rilevamento PHP precedente e omettere del tutto il markup delle immagini non essenziali:

<p>This paragraph is essential content. The image below may be humorous, but it's not critical to the content.</p>
<?php
if ($saveData === false) {
  // Only send this image if `Save-Data` hasn't been detected.
  ?><img src="meme.jpg" alt="One does not simply consume data."><?php
}

Questa tecnica può sicuramente avere un effetto marcato, come puoi vedere nella figura seguente:

Un confronto tra il caricamento di immagini non critiche quando Save-Data è assente e l'omissione delle stesse immagini quando Save-Data è presente.
Un confronto tra il caricamento di immagini non critiche quando Save-Data è assente e l'omissione delle stesse immagini quando Save-Data è presente.

Naturalmente, omettere le immagini non è l'unica possibilità. Puoi anche intervenire su Save-Data per evitare di inviare altre risorse non critiche, come determinati caratteri tipografici.

Ometti i web font non essenziali

Sebbene i web font non costituiscano di solito una parte così importante del payload totale di una determinata pagina come spesso accade per le immagini, sono comunque molto popolari. Inoltre, non consumano una quantità insignificante di dati. Inoltre, il modo in cui i browser recuperano ed eseguono il rendering dei caratteri è più complicato di quanto si possa pensare, con concetti come FOIT, FOUT ed euristiche del browser che rendono il rendering un'operazione complessa.

Potrebbe quindi essere logico escludere i web font non essenziali per gli utenti che desiderano esperienze utente più snelle. Save-Data rende questa operazione ragionevolmente semplice.

Ad esempio, supponiamo che tu abbia incluso Fira Sans di Google Fonts nel tuo sito. Fira Sans è un ottimo carattere per il corpo del testo, ma forse non è così importante per gli utenti che cercano di risparmiare dati. Aggiungendo una classe save-data all'elemento <html> quando è presente l'intestazione Save-Data, possiamo scrivere stili che richiamano inizialmente il carattere tipografico non essenziale, ma poi lo disattivano quando è presente l'intestazione Save-Data:

/* Opt into web fonts by default. */
p,
li {
  font-family: 'Fira Sans', 'Arial', sans-serif;
}

/* Opt out of web fonts if the `save-Data` class is present. */
.save-data p,
.save-data li {
  font-family: 'Arial', sans-serif;
}

Con questo approccio, puoi lasciare lo snippet <link> di Google Fonts al suo posto, perché il browser carica in modo speculativo le risorse CSS (inclusi i web font) applicando prima gli stili al DOM e poi controllando se gli elementi HTML richiamano una delle risorse nel foglio di stile. Se un utente visita il sito con Save-Data attivo, Fira Sans non verrà mai caricato perché il DOM con stile non lo richiama mai. Verrà invece utilizzato Arial. Non è bello come Fira Sans, ma potrebbe essere preferibile per gli utenti che cercano di risparmiare sui loro piani dati.

Riepilogo

L'intestazione Save-Data non ha molte sfumature: è attiva o disattivata e l'applicazione ha l'onere di fornire esperienze appropriate in base alla sua impostazione, indipendentemente dal motivo.

Ad esempio, alcuni utenti potrebbero non consentire la modalità di risparmio dati se sospettano che si verificherà una perdita di contenuti o funzionalità dell'app, anche in una situazione di connettività scarsa. Al contrario, alcuni utenti potrebbero attivarla di routine per mantenere le pagine il più piccole e semplici possibile, anche in una situazione di buona connettività. È meglio che la tua app presupponga che l'utente voglia l'esperienza completa e illimitata, a meno che tu non abbia un'indicazione chiara del contrario tramite un'azione esplicita dell'utente.

In qualità di proprietari di siti e sviluppatori web, assumiamoci la responsabilità di gestire i nostri contenuti per migliorare l'esperienza utente per gli utenti con limitazioni di dati e costi.

Per maggiori dettagli su Save-Data ed esempi pratici eccellenti, consulta Aiuta i tuoi utenti Save Data.