Guida rapida offline

Questo codelab fa parte del corso di formazione Developing Progressive Web Apps, sviluppato dal team Google Training Training. Otterrai il massimo valore da questo corso se lavori in sequenza nei codelab.

Per i dettagli completi sul corso, consulta la panoramica sullo sviluppo di app web progressive.

Introduzione

In questo lab utilizzerai Lighthouse per controllare un sito web per gli standard dell'app web progressiva (PWA). Dovrai anche aggiungere funzionalità offline con l'API del service worker.

Obiettivi didattici

  • Come controllare i siti con Lighthouse
  • Come aggiungere funzionalità offline a un'applicazione

Che cosa devi sapere

  • HTML, CSS e JavaScript di base
  • Familiarità con ESIMO 2015

Cosa ti occorre

  • Computer con accesso terminali/shell
  • Connessione a Internet
  • Browser Chrome (per l'utilizzo di Lighthouse)
  • Un editor di testo
  • (Facoltativo) Chrome su un dispositivo Android

Scarica o clona il repository pwa-training-labs da github e installa la versione LTS di Node.js, se necessario.

Accedi alla directory offline-quickstart-lab/app/ e avvia un server di sviluppo locale:

cd offline-quickstart-lab/app
npm install
node server.js

Puoi arrestare il server in qualsiasi momento con Ctrl-c.

Apri il browser e vai alla pagina localhost:8081/. Dovresti notare che il sito è una pagina web semplice e statica.

Nota: annulla la registrazione di tutti i service worker e cancella tutte le cache di service worker per localhost, in modo da non interferire con il lab. In Chrome DevTools, puoi accedere a Cancella dati sito dalla sezione Cancella spazio di archiviazione della scheda Applicazione.

Apri la cartella offline-quickstart-lab/app/ nell'editor di testo che preferisci. La cartella app/ è il luogo in cui creerai il lab.

Questa cartella contiene:

  • La cartella images/ contiene immagini di esempio
  • styles/main.css è il foglio di stile principale
  • index.html è la pagina HTML principale del nostro sito di esempio
  • package-lock.json e package.json monitorano le dipendenze dell'app (le uniche dipendenze in questo caso si riferiscono al server di sviluppo locale)
  • server.js è un server di sviluppo locale per i test
  • service-worker.js è il file del service worker (al momento vuoto)

Prima di iniziare ad apportare modifiche al sito, sottoponiamo a Lighthouse il controllo per verificare quali aspetti possono essere migliorati.

Torna all'app (in Chrome) e apri la scheda Controlli degli Strumenti per sviluppatori. Dovresti visualizzare l'icona e le opzioni di configurazione di Lighthouse. Seleziona "Dispositivi mobili"; per Dispositivo, seleziona tutti i Controlli, scegli una delle opzioni di Limitazione e scegli Cancella spazio di archiviazione:

Fai clic su Esegui controlli. Il completamento dei controlli richiede alcuni istanti.

Spiegazione

Dovresti vedere un rapporto con i punteggi negli Strumenti per sviluppatori al termine del controllo. Dovrebbe mostrare punteggi di questo tipo (i punteggi potrebbero non essere uguali):

Nota: i punteggi Lighthouse sono un'approssimazione e possono essere influenzati dall'ambiente (ad esempio, se hai aperto una grande quantità di finestre del browser). I tuoi punteggi potrebbero non essere uguali a quelli mostrati qui.

Inoltre, la sezione App web progressiva dovrebbe essere simile a questa:

Il report contiene punteggi e metriche in cinque categorie:

  • App web progressiva
  • Prestazioni
  • Accessibilità
  • Best practice
  • SEO

Come puoi vedere, la nostra app ha un punteggio medio nella categoria delle app web progressive (PWA). Miglioriamo il nostro punteggio!

Dai un'occhiata alla sezione PWA del report e scopri cosa manca.

Registra un service worker

Uno degli errori elencati nel report è che nessun service worker è registrato. Al momento app/service-worker.js ha un file di service worker vuoto.

Aggiungi il seguente script alla fine di index.html, subito prima del tag </body> di chiusura:

<script>
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('service-worker.js')
      .then(reg => {
        console.log('Service worker registered! 😎', reg);
      })
      .catch(err => {
        console.log('😥 Service worker registration failed: ', err);
      });
  });
}
</script>

Spiegazione

Questo codice registra il file vuoto del service worker sw.js quando la pagina è stata caricata. Tuttavia, il file del service worker attuale è vuoto e non farà nulla. Aggiungi il codice di servizio nel passaggio successivo.

Risorse di pre-cache

Un altro errore elencato nel report è che l'app non risponde con un codice di stato 200 quando è offline. Dobbiamo aggiornare il nostro service worker per risolvere il problema.

Aggiungi il seguente codice al file del service worker (sw.js):

const cacheName = 'cache-v1';
const precacheResources = [
  '/',
  'index.html',
  'styles/main.css',
  'images/space1.jpg',
  'images/space2.jpg',
  'images/space3.jpg'
];

self.addEventListener('install', event => {
  console.log('Service worker install event!');
  event.waitUntil(
    caches.open(cacheName)
      .then(cache => {
        return cache.addAll(precacheResources);
      })
  );
});

self.addEventListener('activate', event => {
  console.log('Service worker activate event!');
});

self.addEventListener('fetch', event => {
  console.log('Fetch intercepted for:', event.request.url);
  event.respondWith(caches.match(event.request)
    .then(cachedResponse => {
        if (cachedResponse) {
          return cachedResponse;
        }
        return fetch(event.request);
      })
    );
});

Ora torna al browser e aggiorna il sito. Controlla la console per verificare che il service worker:

  • registrati
  • installata
  • attivato

Nota:se hai già registrato il service worker in precedenza o stai riscontrando problemi con l'attivazione di tutti gli eventi, annulla la registrazione di tutti i service worker e aggiorna la pagina. Se non funziona, chiudi tutte le istanze dell'app e riaprila.

Successivamente, termina il server di sviluppo locale nella riga di comando eseguendo Ctrl + c. Aggiorna di nuovo il sito e osserva che viene caricato anche se il server è offline.

Nota: potresti visualizzare un errore della console che indica che non è stato possibile recuperare il service worker: An unknown error occurred when fetching the script. service-worker.js Failed to load resource: net::ERR_CONNECTION_REFUSED. Questo errore viene visualizzato perché il browser non riesce a recuperare lo script del service worker (perché il sito è offline), ma questo è previsto perché non possiamo utilizzare il service worker per memorizzare la cache. In caso contrario, il browser dell'utente rimane bloccato per sempre sullo stesso service worker.

Spiegazione

Dopo che il service worker è stato registrato dallo script di registrazione in index.html, si verifica l'evento install del service worker. Durante questo evento, il listener di eventi install apre una cache denominata e memorizza nella cache i file specificati con il metodo cache.addAll. Questa condizione è definita "precaching", in quanto si verifica durante l'evento install, che in genere è la prima volta che un utente visita il sito.

Dopo l'installazione e se un altro service worker non è attualmente in grado di controllare la pagina, il nuovo service worker viene "attivato" (il listener di eventi activate viene attivato nel service worker) e inizia a controllare la pagina.

Quando le risorse sono richieste da una pagina controllata da un service worker attivato, le richieste passano attraverso il service worker, come un proxy di rete. Per ogni richiesta viene attivato un evento fetch. Nel nostro service worker, il listener di eventi fetch cerca nella cache e risponde con la risorsa memorizzata nella cache, se disponibile. Se la risorsa non è memorizzata nella cache, viene richiesta normalmente.

La memorizzazione nella cache delle risorse consente all'app di lavorare offline evitando richieste di rete. Ora la nostra app può rispondere con un codice di stato 200 offline.

Nota: l'evento di attivazione non viene utilizzato per scopi diversi da quello di registrazione in questo esempio. L'evento è stato incluso per eseguire il debug dei problemi del ciclo di vita del service worker.

(Facoltativo) Puoi anche vedere le risorse memorizzate nella cache nella scheda Applicazione di Strumenti per sviluppatori espandendo la sezione Spazio di archiviazione cache:

Riavvia il server di sviluppo con node server.js e aggiorna il sito. Dopodiché apri di nuovo la scheda Controlli in Strumenti per sviluppatori ed esegui nuovamente il controllo di Lighthouse selezionando Nuovo controllo (il segno più nell'angolo in alto a sinistra). Al termine del controllo, dovresti vedere che il nostro punteggio PWA è significativamente migliore, ma potremmo comunque migliorare We' continueremo a migliorare il nostro punteggio nella sezione seguente.

Nota: questa sezione è facoltativa perché il test del Banner per l'installazione di app web non rientra nell'ambito del lab. Puoi provare autonomamente utilizzando il debug remoto.

Il nostro punteggio PWA non è ancora eccellente. Alcuni dei restanti errori elencati nel report sono che all'utente non verrà richiesto di installare la nostra app web e che non abbiamo configurato una schermata iniziale o i colori del brand nella barra degli indirizzi. Possiamo risolvere questi problemi e implementare progressivamente Aggiungi alla schermata Home soddisfacendo alcuni criteri aggiuntivi. Più di ogni altra cosa, dobbiamo creare un file manifest.

Creare un file manifest

Crea un file app/ in manifest.json e aggiungi il seguente codice:

{
  "name": "Space Missions",
  "short_name": "Space Missions",
  "lang": "en-US",
  "start_url": "/index.html",
  "display": "standalone",
  "theme_color": "#FF9800",
  "background_color": "#FF9800",
  "icons": [
    {
      "src": "images/touch/icon-128x128.png",
      "sizes": "128x128"
    },
    {
      "src": "images/touch/icon-192x192.png",
      "sizes": "192x192"
    },
    {
      "src": "images/touch/icon-256x256.png",
      "sizes": "256x256"
    },
    {
      "src": "images/touch/icon-384x384.png",
      "sizes": "384x384"
    },
    {
      "src": "images/touch/icon-512x512.png",
      "sizes": "512x512"
    }
  ]
}

Le immagini a cui viene fatto riferimento nel file manifest sono già fornite nell'app.

Quindi aggiungi il seguente HTML alla fine del tag <head> in index.html:

<link rel="manifest" href="manifest.json">

<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="application-name" content="Space Missions">
<meta name="apple-mobile-web-app-title" content="Space Missions">
<meta name="theme-color" content="#FF9800">
<meta name="msapplication-navbutton-color" content="#FF9800">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="msapplication-starturl" content="/index.html">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<link rel="icon" sizes="128x128" href="/images/touch/icon-128x128.png">
<link rel="apple-touch-icon" sizes="128x128" href="/images/touch/icon-128x128.png">
<link rel="icon" sizes="192x192" href="icon-192x192.png">
<link rel="apple-touch-icon" sizes="192x192" href="/images/touch/icon-192x192.png">
<link rel="icon" sizes="256x256" href="/images/touch/icon-256x256.png">
<link rel="apple-touch-icon" sizes="256x256" href="/images/touch/icon-256x256.png">
<link rel="icon" sizes="384x384" href="/images/touch/icon-384x384.png">
<link rel="apple-touch-icon" sizes="384x384" href="/images/touch/icon-384x384.png">
<link rel="icon" sizes="512x512" href="/images/touch/icon-512x512.png">
<link rel="apple-touch-icon" sizes="512x512" href="/images/touch/icon-512x512.png">

Torna al sito. Nella scheda Applicazione di Strumenti per sviluppatori, seleziona la sezione Cancella spazio di archiviazione e fai clic su Cancella dati dei siti. Dopodiché aggiorna la pagina. Ora seleziona la sezione Manifest (Manifest). Dovresti visualizzare le icone e le opzioni di configurazione configurate nel file manifest.json. Se non vedi le modifiche, apri il sito in una finestra di navigazione in incognito e ricontrolla.

Spiegazione

Il file manifest.json indica al browser come applicare uno stile e formattare alcuni degli aspetti progressivi dell'app, come l'icona in Chrome del browser, l'icona della schermata Home e la schermata iniziale. Può essere utilizzato anche per configurare l'apertura dell'app web in modalità standalone, come farebbe un'app nativa (in altre parole, al di fuori del browser).

Al momento della scrittura di questo testo, per alcuni browser è ancora in fase di sviluppo e i tag <meta> configurano un sottoinsieme di queste funzionalità per alcuni browser che non dispongono ancora del supporto completo.

Abbiamo dovuto cancellare i dati del sito per rimuovere la nostra vecchia versione memorizzata nella cache di index.html (dato che la versione non aveva il link manifest). Prova a eseguire un altro controllo di Lighthouse per scoprire quanto è migliorato il punteggio delle PWA.

Attivazione del prompt di installazione

Il passaggio successivo per l'installazione dell'app consiste nel mostrare agli utenti la richiesta di installazione. Chrome 67 richiede automaticamente agli utenti, ma a partire da Chrome 68, la richiesta di installazione deve essere attivata in modo programmatico in risposta al gesto dell'utente.

Aggiungi il pulsante e il banner "Installa app" e il banner nella parte superiore di index.html (subito dopo il tag <main>) con il seguente codice:

<section id="installBanner" class="banner">
    <button id="installBtn">Install app</button>
</section>

Quindi applica uno stile al banner aggiungendo i seguenti stili a styles/main.css:

.banner {
  align-content: center;
  display: none;
  justify-content: center;
  width: 100%;
}

Salva il file. Infine, aggiungi il seguente tag script a index.html:

  <script>
    let deferredPrompt;
    window.addEventListener('beforeinstallprompt', event => {

      // Prevent Chrome 67 and earlier from automatically showing the prompt
      event.preventDefault();

      // Stash the event so it can be triggered later.
      deferredPrompt = event;

      // Attach the install prompt to a user gesture
      document.querySelector('#installBtn').addEventListener('click', event => {

        // Show the prompt
        deferredPrompt.prompt();

        // Wait for the user to respond to the prompt
        deferredPrompt.userChoice
          .then((choiceResult) => {
            if (choiceResult.outcome === 'accepted') {
              console.log('User accepted the A2HS prompt');
            } else {
              console.log('User dismissed the A2HS prompt');
            }
            deferredPrompt = null;
          });
      });

      // Update UI notify the user they can add to home screen
      document.querySelector('#installBanner').style.display = 'flex';
    });
  </script>

Salva il file. Apri l'app in Chrome su un dispositivo Android utilizzando il debug remoto. Quando la pagina viene caricata, dovresti vedere il pulsante "Installa app" (non la vedrai su un computer desktop, pertanto assicurati di testarla). Fai clic sul pulsante e dovrebbe essere visualizzata la finestra Aggiungi alla schermata Home. Segui la procedura per installare l'app sul dispositivo. Al termine dell'installazione, dovresti essere in grado di aprire l'app web in modalità autonoma (esterna al browser) toccando l'icona della schermata Home appena creata.

Spiegazione

Il codice HTML &AMP aggiunge un banner e un pulsante nascosti che possono essere utilizzati dagli utenti per attivare la richiesta di installazione.

Una volta attivato l'evento beforeinstallprompt, impediamo l'esperienza predefinita (in cui Chrome 67 e versioni precedenti richiedono automaticamente agli utenti di eseguire l'installazione) e acquisisci beforeinstallevent nella variabile deferredPrompt globale. Il pulsante "Installa app" viene quindi configurato per mostrare la richiesta con il metodo prompt() di beforeinstallevent. Dopo che l'utente ha effettuato una scelta (da installare o meno), la promessa userChoice si risolve con la scelta dell'utente (outcome). Infine, viene mostrato il pulsante di installazione quando tutto è pronto.

Hai imparato a controllare i siti con Lighthouse e a implementare le nozioni di base sulle funzionalità offline. Se hai completato le sezioni facoltative, hai imparato anche a installare app web sulla schermata Home.

Altre risorse

Lighthouse è open source. Puoi crearlo con un fork, aggiungere i tuoi test e segnalare bug. Lighthouse è disponibile anche come strumento a riga di comando per l'integrazione con i processi di build.

Per visualizzare tutti i codelab nel corso di formazione per PWA, vedi il codelab di benvenuto per il corso/