Creazione di esperienze di ricerca resilienti con Workbox

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

Misura

Prima di aggiungere ottimizzazioni, è sempre opportuno analizzare lo stato attuale dell'applicazione.

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

Nella nuova scheda appena aperta, controlla il comportamento del sito web quando è offline:

  1. Premi "Ctrl+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 demo inserisci una query di ricerca, quindi fai clic sul pulsante Cerca.

Viene visualizzata la pagina di errore standard del browser:

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 pre-cache, in modo che possa essere sempre memorizzata nella cache all'evento install del service worker.

In genere, è necessario indicare a Workbox di aggiungere questo file all'elenco di pre-cache al momento della build, integrando la libreria con lo strumento di creazione che preferisci (ad es. webpack o gulp).

Per semplicità, l'abbiamo già fatto per te. A tale scopo, utilizza il seguente codice su public/sw.js:

const FALLBACK_HTML_URL = '/index_offline.html';

workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);

Successivamente, aggiungi il codice per utilizzare la pagina offline come risposta di riserva:

  1. Per visualizzare la fonte, premi Visualizza origine.
  2. Aggiungi il seguente codice in fondo a 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 effettua 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, viene restituita una pagina HTML offline di riserva.

Per testare questa funzionalità:

  1. Torna all'altra scheda su cui è in esecuzione la tua app.
  2. Imposta nuovamente l'elenco a discesa Limitazione su Online.
  3. Premi il pulsante Indietro di Chrome per tornare alla pagina di ricerca.
  4. Assicurati che la casella di controllo Disabilita cache in DevTools sia disattivata.
  5. Tieni premuto a lungo il pulsante Ricarica di Chrome e seleziona Svuota la cache e ricarica manualmente per assicurarti che il Service worker sia aggiornato.
  6. Imposta nuovamente l'elenco a discesa Limitazione 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 autorizzazione alle notifiche

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

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

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

Il codice effettua le seguenti operazioni:

  • Quando l'utente fa clic su Iscriviti alle 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.
  • Trasmette a showOfflineText() l'autorizzazione risolta per mostrare il testo appropriato all'utente.

Mantieni le query offline e riprova quando sarai di nuovo online

Successivamente, implementa la sincronizzazione in background della casella di lavoro per rendere persistenti le query offline, in modo da poterle ritentare quando il browser rileva che la connettività è stata restituita.

  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 effettua le seguenti operazioni:

  • workbox.backgroundSync.Plugin contiene la logica per aggiungere le richieste non riuscite a una coda in modo da poterle ritentare in un secondo momento. Queste richieste saranno permanenti in IndexedDB.
  • maxRetentionTime indica per quanto tempo è possibile ritentare una richiesta. In questo caso abbiamo scelto 60 minuti (dopo i quali verranno eliminati).
  • onSync è la parte più importante di questo codice. Questo callback verrà chiamato quando verrà ripristinata la connessione, in modo che le richieste in coda vengano recuperate e poi recuperate dalla rete.
  • La risposta di rete viene aggiunta alla cache di 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 trasmetti il valore bgSyncPlugin definito in precedenza. Aggiungi il seguente codice in fondo a 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.

Poi, aggiungi il codice seguente alla fine di public/sw.js per definire una strategia di memorizzazione nella cache per le richieste provenienti dalle notifiche. Utilizzare una strategia CacheFirst, in modo che possa essere fornita 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)
  );
});

Testa la funzionalità

  1. Torna all'altra scheda su cui è in esecuzione la tua app.
  2. Imposta nuovamente l'elenco a discesa Limitazione su Online.
  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 la cache e ricarica manualmente per assicurarti che il Service worker sia aggiornato.
  5. Imposta nuovamente l'elenco a discesa Limitazione 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 a inviare notifiche, fai clic su Consenti.
  9. Inserisci un'altra query di ricerca e fai nuovamente clic sul pulsante Cerca.
  10. Imposta nuovamente l'elenco a discesa Limitazione su Online.

Una volta ripristinata la connessione, verrà visualizzata una notifica:

Uno screenshot dell'intero flusso offline.

Conclusione

Workbox offre 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 Workbox, per assicurarti che le query utente offline non vengano perse ed è possibile riprovare una volta ripristinata la connessione. La demo è un'app di ricerca semplice, ma puoi utilizzare un'implementazione simile per scenari e casi d'uso più complessi, inclusi app di chat, pubblicazione di messaggi su un social network e così via.