Sincronizzazione in background

Jake Archibald
Jake Archibald

Background Synchronization è una nuova API web che ti consente di posticipare le azioni finché l'utente non dispone di una connettività stabile. Ciò garantisce che tutto ciò che l'utente vuole inviare venga effettivamente inviato.

Il problema

Internet è un ottimo posto per perdere tempo. Se non sprecassimo tempo su internet, non sapremmo che i gatti non amano i fiori, che i camaleoni adorano le bolle o che il nostro Eric Bidelman è un eroe del minigolf di fine anni'90.

Ma a volte, solo a volte, non vogliamo perdere tempo. L'esperienza utente auspicata è più simile a:

  1. Smartphone fuori dalla tasca.
  2. Raggiungere un obiettivo secondario.
  3. Smartphone di nuovo in tasca.
  4. Riprendi la tua vita.

Purtroppo questa esperienza viene spesso interrotta da una scarsa connettività. Può capitare. Stai fissando una schermata bianca o una rotellina e sai che dovresti semplicemente arrenderti e andare avanti, ma aspetti altri 10 secondi per sicurezza. Dopo 10 secondi? Niente.

Ma perché rinunciare ora? Hai già investito tempo, quindi andarsene senza ottenere nulla sarebbe uno spreco, quindi continui ad aspettare. A questo punto vorresti arrenderti, ma sai che il secondo in cui lo fai è quello che precede il caricamento di tutto, se solo avessi aspettato.

I service worker risolvono la parte di caricamento della pagina consentendoti di pubblicare contenuti da una cache. E se la pagina deve inviare qualcosa al server?

Al momento, se l'utente preme "Invia" su un messaggio, deve fissare la rotellina fino al completamento. Se l'utente tenta di uscire o chiudere la scheda, utilizziamo onbeforeunload per visualizzare un messaggio come "No, devo chiederti di guardare ancora questo cursore. Mi dispiace". Se l'utente non ha una connessione, diciamo "Mi dispiace, devi tornare più tardi e riprovare".

Questa è spazzatura. La sincronizzazione in background ti consente di fare di più.

Soluzione

Il video seguente mostra Emojoy, una demo di chat solo con emoji. Si tratta di un'app web progressiva che funziona principalmente offline. L'app utilizza messaggi e notifiche push e la sincronizzazione in background.

Se l'utente tenta di inviare un messaggio quando non ha alcuna connettività, fortunatamente il messaggio viene inviato in background quando la connettività viene ripristinata.

A partire da marzo 2016, la sincronizzazione in background è disponibile in Chrome a partire dalla versione 49. Per visualizzarla, segui questi passaggi:

  1. Apri Emojoy.
  2. Passa alla modalità offline (utilizzando la modalità aereo o visitando una gabbia di Faraday locale).
  3. Digita un messaggio.
  4. Torna alla schermata Home (se vuoi, chiudi la scheda o il browser).
  5. Vai online.
  6. Il messaggio viene inviato in background.

La possibilità di inviare messaggi in background come questo comporta anche un miglioramento percepito delle prestazioni. L'app non deve fare tanto caso all'invio del messaggio, quindi può aggiungerlo immediatamente all'output.

Come richiedere una sincronizzazione in background

In vero stile web estensibile, si tratta di una funzionalità di basso livello che ti offre la libertà di fare ciò che ti serve. Chiedi di attivare un evento quando l'utente ha connettività, che è immediata se l'utente ha già connettività. Dopodiché, ascolta l'evento e fai ciò che occorre.

Come la messaggistica push, utilizza un service worker come target dell'evento, il che gli consente di funzionare quando la pagina non è aperta. Per iniziare, registrati per una sincronizzazione da una pagina:

// Register your service worker:
navigator.serviceWorker.register('/sw.js');

// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
  return swRegistration.sync.register('myFirstSync');
});
 ```

Then listen for the event in `/sw.js`:

```js
self.addEventListener('sync', function(event) {
  if (event.tag == 'myFirstSync') {
    event.waitUntil(doSomeStuff());
  }
});

È tutto. In base a quanto riportato sopra, doSomeStuff() dovrebbe restituire una promessa che indica l'esito positivo o negativo di qualsiasi operazione. Se viene soddisfatta, la sincronizzazione è completa. In caso di errore, verrà pianificata un'altra sincronizzazione per riprovare. Anche le sincronizzazioni con nuovi tentativi aspettano la connettività e utilizzano un backoff esponenziale.

Il nome del tag della sincronizzazione ("myFirstSync" nell'esempio precedente) deve essere univoco per una determinata sincronizzazione. Se registri una sincronizzazione utilizzando lo stesso tag di una sincronizzazione in attesa, questa viene unita alla sincronizzazione esistente. Ciò significa che puoi registrarti per una sincronizzazione di "cancellazione in uscita" ogni volta che l'utente invia un messaggio, ma se invia 5 messaggi mentre sei offline, riceverai una sola sincronizzazione quando saranno online. Se vuoi 5 eventi di sincronizzazione distinti, utilizza semplicemente tag univoci.

Ecco una semplice demo che esegue il minimo indispensabile: utilizza l'evento di sincronizzazione per mostrare una notifica.

Per cosa posso utilizzare la sincronizzazione in background?

Idealmente, dovresti utilizzarlo per pianificare l'invio di dati che ti interessano oltre la durata della pagina. Messaggi di chat, email, aggiornamenti dei documenti, modifiche alle impostazioni, caricamenti di foto e così via: tutto ciò che vuoi che raggiunga il server anche se l'utente esce dalla pagina o chiude la scheda. La pagina potrebbe archiviarli in un archivio "Posta in uscita" in indexedDB, che il service worker recupererà e invierà.

Tuttavia, puoi utilizzarlo anche per recuperare piccoli bit di dati…

Un'altra demo!

Questa è la demo di Wikipedia offline che ho creato per Supercharging Page Load. Da allora ho aggiunto un po' di magia alla sincronizzazione in background.

Prova tu stesso. Assicurati di utilizzare Chrome 49 o versioni successive, quindi:

  1. Vai a qualsiasi articolo, ad esempio Chrome.
  2. Passare alla modalità offline (utilizzando la modalità aereo o sottoscrivendo un abbonamento con un operatore mobile pessimo come il mio).
  3. Fai clic su un link a un altro articolo.
  4. Dovresti ricevere un messaggio che ti informa che il caricamento della pagina non è riuscito (questo messaggio viene visualizzato anche se il caricamento della pagina richiede un po' di tempo).
  5. Accettare le notifiche.
  6. Chiudi il browser.
  7. Vai online
  8. Riceverai una notifica quando l'articolo viene scaricato, memorizzato nella cache e pronto per essere visualizzato.

Con questo modello, l'utente può mettere lo smartphone in tasca e continuare a svolgere le sue attività, sapendo che lo smartphone lo avviserà quando avrà recuperato ciò che cercava.

Autorizzazioni

Le demo che ho mostrato utilizzano le notifiche web, che richiedono l'autorizzazione, ma la sincronizzazione in background non richiede autorizzazioni.

Gli eventi di sincronizzazione vengono spesso completati quando l'utente ha una pagina del sito aperta, quindi richiedere l'autorizzazione dell'utente sarebbe un'esperienza negativa. Per evitare abusi, stiamo invece limitando il momento in cui le sincronizzazioni possono essere registrate e attivate. Ad esempio:

  • Puoi registrare un evento di sincronizzazione solo quando l'utente ha una finestra aperta sul sito.
  • Il tempo di esecuzione degli eventi è limitato, quindi non puoi utilizzarli per eseguire ping a un server ogni x secondi, per minare bitcoin o altro.

Naturalmente, queste limitazioni possono essere allentate o rafforzate in base all'utilizzo effettivo.

Miglioramento progressivo

Ci vorrà del tempo prima che tutti i browser supportino la sincronizzazione in background, soprattutto perché Safari ed Edge non supportano ancora i service worker. Ma il miglioramento progressivo aiuta in questi casi:

if ('serviceWorker' in navigator && 'SyncManager' in window) {
  navigator.serviceWorker.ready.then(function(reg) {
    return reg.sync.register('tag-name');
  }).catch(function() {
    // system was unable to register for a sync,
    // this could be an OS-level restriction
    postDataFromThePage();
  });
} else {
  // serviceworker/sync not supported
  postDataFromThePage();
}

Se i worker di servizio o la sincronizzazione in background non sono disponibili, pubblica semplicemente i contenuti della pagina come faresti normalmente.

Vale la pena utilizzare la sincronizzazione in background anche se la connettività dell'utente sembra buona, in quanto ti protegge da navigazioni e chiusure di schede durante l'invio dei dati.

Il futuro

Prevediamo di rilasciare la sincronizzazione in background in una versione stabile di Chrome nella prima metà del 2016, mentre stiamo lavorando a una variante, la "sincronizzazione in background periodica". Con la sincronizzazione in background periodica, puoi richiedere un evento limitato dall'intervallo di tempo, dallo stato della batteria e dallo stato della rete. Naturalmente ciò richiederebbe l'autorizzazione dell'utente e spetta al browser decidere quando e con quale frequenza vengono attivati. In altre parole, un sito di notizie potrebbe richiedere la sincronizzazione ogni ora, ma il browser potrebbe sapere che lo leggi solo alle 07:00, quindi la sincronizzazione verrà eseguita ogni giorno alle 06:50. Questa idea è un po' più lontana rispetto alla sincronizzazione una tantum, ma è in arrivo.

A poco a poco stiamo portando sul web i pattern di successo di Android e iOS, mantenendo al contempo ciò che rende il web fantastico.