Creazione di esperienze di ricerca resilienti con Workbox

Questo codelab mostra come implementare un'esperienza di ricerca resiliente con Workbox. L'app di dimostrazione utilizzata contiene una casella di ricerca che chiama un endpoint del server e reindirizza l'utente a una pagina HTML di base.

Misura

Prima di aggiungere le ottimizzazioni, è sempre buona prassi analizzare lo stato attuale dell'applicazione.

  • Fai clic su Remix per modificare per rendere il progetto modificabile.
  • Per visualizzare l'anteprima del sito, premi Visualizza app. Quindi premi A schermo intero schermo intero.

Nella nuova scheda appena aperta, controlla il comportamento del sito web quando passa alla modalità offline:

  1. Premi "Control+Maiusc+J" (o "Comando+Opzione+J" su Mac) per aprire DevTools.
  2. Fai clic sulla scheda Rete.
  3. Apri Chrome DevTools e seleziona il riquadro Rete.
  4. Nell'elenco a discesa Limitazione, seleziona Offline.
  5. Nell'app di demo, inserisci una query di ricerca e fai clic sul pulsante Cerca.

Viene visualizzata la pagina di errore del browser standard:

Uno screenshot dell'esperienza utente offline predefinita nel browser.

Fornire una risposta di riserva

Il service worker contiene il codice per aggiungere la pagina offline all'elenco di precache, in modo che possa essere sempre memorizzata nella cache all'evento install del service worker.

In genere, devi chiedere a Workbox di aggiungere questo file all'elenco di precache al momento della compilazione, integrando la libreria con lo strumento di compilazione che preferisci (ad es. webpack o gulp).

Per semplificare, abbiamo già fatto tutto noi. Il seguente codice in public/sw.js esegue questa operazione:

const FALLBACK_HTML_URL = '/index_offline.html';
…
workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);

Aggiungi il codice per utilizzare la pagina offline come risposta di riserva:

  1. Per visualizzare il codice sorgente, premi Visualizza sorgente.
  2. Aggiungi il seguente codice alla fine di public/sw.js:
workbox.routing.setDefaultHandler(new workbox.strategies.NetworkOnly());

workbox.routing.setCatchHandler(({event}) => {
  switch (event.request.destination) {
    case 'document':
      return caches.match(FALLBACK_HTML_URL);
      break;
    default:
      return Response.error();
  }
});

Il codice esegue le seguenti operazioni:

  • Definisce una strategia Solo rete predefinita che verrà applicata a tutte le richieste.
  • Dichiara un gestore degli errori globale chiamando workbox.routing.setCatchHandler() per gestire le richieste non riuscite. Quando le richieste riguardano documenti, verrà restituita una pagina HTML offline di riserva.

Per testare questa funzionalità:

  1. Torna all'altra scheda in cui è in esecuzione la tua app.
  2. Ripristina l'impostazione Online nell'elenco a discesa Ritardo.
  3. Premi il pulsante Indietro di Chrome per tornare alla pagina di ricerca.
  4. Assicurati che la casella di controllo Disattiva cache in DevTools sia disattivata.
  5. Tieni premuto a lungo il pulsante Ricarica di Chrome e seleziona Svuota cache e ricarica forzata per assicurarti che il tuo worker di servizio sia aggiornato.
  6. Imposta di nuovo l'elenco a discesa Ritardo su Offline.
  7. Inserisci una query di ricerca e fai di nuovo clic sul pulsante Cerca.

Viene visualizzata la pagina HTML di riserva:

Uno screenshot dell'esperienza utente offline personalizzata nel browser.

Richiedi l'autorizzazione alle notifiche

Per semplicità, la pagina offline all'indirizzo views/index_offline.html contiene già il codice per richiedere le autorizzazioni di notifica in un blocco di script in basso:

function requestNotificationPermission(event) {
  event.preventDefault();

  Notification.requestPermission().then(function (result) {
    showOfflineText(result);
  });
}

Il codice esegue le seguenti operazioni:

  • Quando l'utente fa clic su Iscriviti per ricevere notifiche, viene chiamata la funzione requestNotificationPermission(), che chiama Notification.requestPermission() per mostrare la richiesta di autorizzazione del browser predefinita. La promessa viene risolta con l'autorizzazione scelta dall'utente, che può essere granted, denied o default.
  • Passa l'autorizzazione risolta a showOfflineText() per mostrare all'utente il testo appropriato.

Mantieni le query offline e riprova quando sei di nuovo online

Successivamente, implementa Workbox Background Sync per mantenere le query offline, in modo che possano essere riprovate quando il browser rileva che la connettività è tornata.

  1. Apri public/sw.js per la modifica.
  2. Aggiungi il seguente codice alla fine del file:
const bgSyncPlugin = new workbox.backgroundSync.Plugin('offlineQueryQueue', {
  maxRetentionTime: 60,
  onSync: async ({queue}) => {
    let entry;
    while ((entry = await queue.shiftRequest())) {
      try {
        const response = await fetch(entry.request);
        const cache = await caches.open('offline-search-responses');
        const offlineUrl = `${entry.request.url}&notification=true`;
        cache.put(offlineUrl, response);
        showNotification(offlineUrl);
      } catch (error) {
        await this.unshiftRequest(entry);
        throw error;
      }
    }
  },
});

Il codice esegue le seguenti operazioni:

  • workbox.backgroundSync.Plugin contiene la logica per aggiungere le richieste non riuscite a una coda in modo che possano essere riprovate in un secondo momento. Queste richieste verranno mantenute in IndexedDB.
  • maxRetentionTime indica il periodo di tempo per cui è possibile riprovare a inviare una richiesta. In questo caso abbiamo scelto 60 minuti (dopodiché verranno eliminati).
  • onSync è la parte più importante di questo codice. Questo callback verrà chiamato quando la connessione sarà ripristinata in modo che le richieste in coda vengano recuperate e poi recuperate dalla rete.
  • La risposta di rete viene aggiunta alla cache offline-search-responses, aggiungendo il parametro di query &notification=true, in modo che questa voce della cache possa essere rilevata quando un utente fa clic sulla notifica.

Per integrare la sincronizzazione in background con il tuo servizio, definisci una strategia NetworkOnly per le richieste all'URL di ricerca (/search_action) e passa il valore bgSyncPlugin definito in precedenza. Aggiungi il seguente codice alla fine di public/sw.js:

const matchSearchUrl = ({url}) => {
  const notificationParam = url.searchParams.get('notification');
  return url.pathname === '/search_action' && !(notificationParam === 'true');
};

workbox.routing.registerRoute(
  matchSearchUrl,
  new workbox.strategies.NetworkOnly({
    plugins: [bgSyncPlugin],
  }),
);

Questo indica a Workbox di accedere sempre alla rete e, quando le richieste non vanno a buon fine, di utilizzare la logica di sincronizzazione in background.

Aggiungi il seguente codice alla fine di public/sw.js per definire una strategia di memorizzazione nella cache per le richieste provenienti dalle notifiche. Utilizza una strategia CacheFirst, in modo che possano essere pubblicati dalla cache.

const matchNotificationUrl = ({url}) => {
  const notificationParam = url.searchParams.get('notification');
  return (url.pathname === '/search_action' && (notificationParam === 'true'));
};

workbox.routing.registerRoute(matchNotificationUrl,
  new workbox.strategies.CacheFirst({
     cacheName: 'offline-search-responses',
  })
);

Infine, aggiungi il codice per mostrare le notifiche:

function showNotification(notificationUrl) {
  if (Notification.permission) {
     self.registration.showNotification('Your search is ready!', {
        body: 'Click to see you search result',
        icon: '/img/workbox.jpg',
        data: {
           url: notificationUrl
        }
     });
  }
}

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
     clients.openWindow(event.notification.data.url)
  );
});

Testare la funzionalità

  1. Torna all'altra scheda in cui è in esecuzione la tua app.
  2. Ripristina l'impostazione Online nell'elenco a discesa Ritardo.
  3. Premi il pulsante Indietro di Chrome per tornare alla pagina di ricerca.
  4. Tieni premuto a lungo il pulsante Ricarica di Chrome e seleziona Svuota cache e ricarica forzata per assicurarti che il tuo worker di servizio sia aggiornato.
  5. Imposta di nuovo l'elenco a discesa Ritardo su Offline.
  6. Inserisci una query di ricerca e fai di nuovo clic sul pulsante Cerca.
  7. Fai clic su Iscriviti alle notifiche.
  8. Quando Chrome ti chiede se vuoi concedere all'app l'autorizzazione per inviare notifiche, fai clic su Consenti.
  9. Inserisci un'altra query di ricerca e fai di nuovo clic sul pulsante Cerca.
  10. Imposta di nuovo l'elenco a discesa Ritardo su Online.

Una volta ripristinata la connessione, viene visualizzata una notifica:

Uno screenshot del flusso offline completo.

Conclusione

Workbox fornisce molte funzionalità integrate per rendere le tue PWA più resilienti e coinvolgenti. In questo codelab hai esplorato come implementare l'API Background Sync tramite l'astrazione di Workbox per assicurarti che le query degli utenti offline non vengano perse e che sia possibile riprovare una volta ripristinata la connessione. La demo è una semplice app di ricerca, ma puoi utilizzare un'implementazione simile per scenari e casi d'uso più complessi, tra cui app di chat, pubblicazione di messaggi su un social network e così via.