Guide de démarrage rapide pour l'accès hors connexion

Cet atelier de programmation fait partie du cours de développement des progressive web apps, développé par l'équipe de formation Google Developers. Exploitez tout le potentiel de ce cours en suivant les ateliers de programmation dans l'ordre.

Pour en savoir plus, consultez la Présentation des progressive web apps.

Introduction

Dans cet atelier, vous allez utiliser Lighthouse pour auditer un site Web afin de vérifier qu'il respecte les normes de progressive web app (PWA). Vous allez également ajouter une fonctionnalité hors connexion à l'aide de l'API Service Worker.

Points abordés

  • Auditer les sites avec Lighthouse
  • Ajouter des fonctionnalités hors connexion à une application

Bon à savoir

  • Code HTML, CSS et JavaScript de base
  • Bonne connaissance des promesses ES2015

Ce dont vous avez besoin

  • Ordinateur avec accès au terminal/shell
  • Connexion à Internet
  • Navigateur Chrome (pour utiliser Lighthouse)
  • Un éditeur de texte
  • Facultatif: Chrome sur un appareil Android

Téléchargez ou clonez le dépôt pwa-training-labsà partir de GitHub, puis installez la version LTS de Node.js, si nécessaire.

Accédez au répertoire offline-quickstart-lab/app/ et démarrez un serveur de développement local:

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

Vous pouvez mettre fin au serveur à tout moment avec Ctrl-c.

Ouvrez votre navigateur et accédez à localhost:8081/. Le site doit être une page Web simple et statique.

Remarque:Annulez l'enregistrement des nœuds de calcul de service et videz le cache de tous les nœuds de calcul de l'hôte local afin qu'ils n'interfèrent pas avec l'atelier. Pour ce faire, cliquez sur Effacer les données du site dans la section Effacer les données de stockage de l'onglet Application dans les outils pour les développeurs Chrome.

Ouvrez le dossier offline-quickstart-lab/app/ dans l'éditeur de texte de votre choix. Le dossier app/ correspond à l'endroit où vous allez créer l'atelier.

Ce dossier contient:

  • Le dossier images/ contient des exemples d'images
  • styles/main.css est la feuille de style principale.
  • index.html est la page HTML principale de notre exemple de site.
  • package-lock.json et package.json suivent les dépendances de l'application (dans ce cas, les seules dépendances sont pour le serveur de développement local).
  • server.js est un serveur de développement local pour les tests
  • service-worker.js est le fichier du service worker (actuellement vide)

Avant de modifier le site, examinons-le avec Lighthouse pour identifier les points à améliorer.

Retournez dans l'application (dans Chrome), puis ouvrez l'onglet Audits dans les outils de développement. L'icône Lighthouse et les options de configuration doivent s'afficher. Sélectionnez "Mobile" pour Appareil, puis Tous les audits, choisissez l'une des options Limitation et choisissez Effacer l'espace de stockage :

Cliquez sur Effectuer des audits. Les audits prennent quelques instants.

Explanation

Une fois l'audit terminé, un rapport présentant les scores dans les outils pour les développeurs doit s'afficher. Les scores devraient s'afficher comme suit :

Remarque : Les scores Lighthouse sont une approximation et peuvent être influencés par votre environnement (par exemple, si vous avez un grand nombre de fenêtres de navigateur ouvertes). Il est possible que vos scores ne soient pas exactement les mêmes que ceux indiqués ici.

La section Progressive Web App doit ressembler à ceci:

Le rapport comprend des scores et des statistiques dans cinq catégories:

  • Progressive web app
  • Performance
  • Accessibilité
  • Bonnes pratiques
  • SEO

Comme vous pouvez le constater, la popularité de notre application est faible dans la catégorie des progressive web apps (PWA). Améliorez notre score !

Prenez le temps de parcourir la section du rapport sur la PWA et d'identifier les éléments manquants.

Enregistrer un service worker

L'un des échecs indiqués dans le rapport est qu'aucun service worker n'est enregistré. Nous disposons actuellement d'un fichier Service Worker vide à l'adresse app/service-worker.js.

Ajoutez le script suivant au bas de index.html, juste avant la balise de fermeture </body>:

<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>

Explanation

Ce code enregistre le fichier vide du service worker sw.js une fois la page chargée. Cependant, le fichier du service worker actuel est vide et n'effectue aucune action. Ajoutez un code de service à l'étape suivante.

Ressources de mise en cache

Autre erreur : l'application ne répond pas avec un code d'état 200 en mode hors connexion. Pour résoudre ce problème, nous devons mettre à jour notre service worker.

Ajoutez le code suivant au fichier du 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);
      })
    );
});

Revenez maintenant au navigateur et actualisez le site. Accédez à la console pour vérifier que le service worker:

  • enregistrés
  • application installée
  • Activé

Remarque : Si vous avez déjà enregistré le service worker ou si vous rencontrez des difficultés pour déclencher tous les événements, annulez l'enregistrement des service worker et actualisez la page. Si cette méthode ne fonctionne pas, fermez toutes les instances de l'application, puis rouvrez-la.

Ensuite, arrêtez le serveur de développement local dans votre ligne de commande en exécutant Ctrl + c. Actualisez à nouveau la page et observez qu'elle se charge même si le serveur est hors connexion.

Remarque:Une erreur de console peut indiquer que le service worker n'a pas pu être récupéré: An unknown error occurred when fetching the script. service-worker.js Failed to load resource: net::ERR_CONNECTION_REFUSED. Cette erreur s'affiche, car le navigateur n'a pas pu récupérer le script du service worker (car le site est hors connexion), mais cette action est attendue, car nous ne pouvons pas l'utiliser pour la mise en cache. sans quoi le navigateur de l'utilisateur resterait bloqué indéfiniment.

Explanation

Une fois que le service worker a été enregistré par le script d'inscription dans index.html, l'événement install associé a lieu. Pendant cet événement, l'écouteur d'événements install ouvre un cache nommé et met en cache les fichiers spécifiés avec la méthode cache.addAll. C'est ce que l'on appelle le"précaution", car elle a lieu pendant l'événement install, qui correspond généralement à la première visite d'un utilisateur sur votre site.

Une fois qu'un service worker a été installé, et qu'un autre service worker ne contrôle pas actuellement la page, le nouveau service worker est "activé" (l'écouteur d'événements activate est déclenché dans le service worker) et commencera à contrôler la page.

Lorsqu'une page est demandée par un service worker activé, elle est transmise via le service worker (un proxy réseau, par exemple). Un événement fetch est déclenché pour chaque requête. Dans notre service worker, l'écouteur d'événements fetch recherche les caches et répond avec la ressource en cache si celle-ci est disponible. Si la ressource n'est pas mise en cache, elle est demandée normalement.

La mise en cache des ressources permet à l'application de fonctionner hors connexion en évitant les requêtes réseau. Désormais, notre application peut afficher un code d'état 200 hors connexion.

Remarque : L'événement d'activation n'est utilisé que dans le cadre de la connexion dans cet exemple. Cet événement a été inclus pour faciliter le débogage des problèmes de cycle de vie des nœuds de calcul de service.

Facultatif : Vous pouvez également consulter les ressources mises en cache dans l'onglet Application des outils de développement en développant la section Cache Storage:

Redémarrez le serveur de développement avec node server.js et actualisez le site. Ensuite, ouvrez à nouveau l'onglet Audits des outils pour les développeurs et relancez l'audit Lighthouse en sélectionnant Nouvel audit (signe Plus en haut à gauche). Une fois l'audit terminé, le score de la PWA devrait s'améliorer considérablement, mais l'amélioration de notre taux de performances pourra être améliorée dans la section suivante.

Remarque:Cette section est facultative, car les tests d'installation d'applications Web dépassent le cadre de l'atelier. Vous pouvez l'essayer par vous-même à l'aide du débogage à distance.

Le score de la PWA n'est pas parfait. Parmi les derniers échecs répertoriés dans le rapport, citons le fait que l'utilisateur ne sera pas invité à installer notre application Web, et que nous n'avons pas configuré d'écran d'accueil ni de couleurs de marque dans la barre d'adresse. Nous pouvons résoudre ces problèmes et implémenter progressivement l'option Ajouter à l'écran d'accueil en répondant à des critères supplémentaires. Plus important encore, nous devons créer un fichier manifeste.

Créer un fichier manifeste

Dans app/, créez un fichier nommé manifest.json et ajoutez le code suivant:

{
  "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"
    }
  ]
}

Les images référencées dans le fichier manifeste sont déjà fournies dans l'application.

Ensuite, ajoutez le code HTML suivant en bas de la balise <head> dans 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">

Revenez sur le site. Dans l'onglet Application des outils pour les développeurs, sélectionnez la section Effacer les données de stockage, puis cliquez sur Effacer les données du site. Actualisez ensuite la page. Sélectionnez ensuite la section Manifest (Fichier manifeste). Les icônes et options de configuration configurées dans le fichier manifest.json doivent s'afficher. Si vos modifications ne s'affichent pas, ouvrez-le dans une fenêtre de navigation privée et vérifiez à nouveau.

Explanation

Le fichier manifest.json indique au navigateur comment appliquer un style à certains aspects progressifs de votre application et les mettre en forme, comme le navigateur Chrome, l'icône de l'écran d'accueil et l'écran d'accueil. Elle permet également de configurer votre application Web pour qu'elle s'ouvre en mode standalone, comme une application native (en dehors du navigateur).

Certains navigateurs sont toujours en cours de développement, et les balises <meta> configurent un sous-ensemble de ces fonctionnalités pour certains navigateurs qui ne sont pas encore compatibles.

Nous avons dû effacer les données du site pour supprimer l'ancienne version en cache de index.html (puisque cette version ne comportait pas le lien manifeste). Exécutez un autre audit Lighthouse pour voir dans quelle mesure le score de la PWA s'est amélioré.

Activation de l'invite d'installation

L'étape suivante pour installer notre application consiste à présenter aux utilisateurs l'invite d'installation. Chrome 67 invitait les utilisateurs automatiquement, mais à partir de Chrome 68, l'invite d'installation devrait être activée par programmation en réponse à un geste de l'utilisateur.

Ajoutez un bouton &installer l'application&la bannière en haut de index.html (juste après la balise <main>) avec le code suivant:

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

Ensuite, stylisez la bannière en ajoutant les styles suivants à styles/main.css:

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

Enregistrez le fichier. Enfin, ajoutez la balise de script suivante à 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>

Enregistrez le fichier. Ouvrez l'application dans Chrome sur un appareil Android à l'aide du débogage à distance. Lors du chargement de la page, le bouton "Installer l'application" devrait s'afficher. Comme vous ne l'aurez pas, vous devez l'afficher sur un ordinateur. Par conséquent, assurez-vous de le tester sur un appareil mobile. Cliquez sur le bouton. L'invite "Ajouter à l'écran d'accueil" devrait s'afficher. Suivez les étapes pour installer l'application sur votre appareil. Après l'installation, vous devriez pouvoir ouvrir l'application Web en mode autonome (en dehors du navigateur) en appuyant sur l'icône de l'écran d'accueil que vous venez de créer.

Explanation

Le code HTML et CSS ajoute une bannière et un bouton cachés qui permettent aux utilisateurs d'activer l'invite d'installation.

Une fois l'événement beforeinstallprompt déclenché, nous empêchons l'expérience par défaut (dans laquelle Chrome 67 et versions antérieures invitent automatiquement les utilisateurs à installer) et capturez le beforeinstallevent dans la variable globale deferredPrompt. Le bouton "Installer l'application" est ensuite configuré pour afficher l'invite avec la méthode beforeinstallevent's prompt(). Une fois que l'utilisateur a fait un choix (installer ou non) la promesse userChoice se résout avec le choix de l'utilisateur (outcome). Enfin, nous affichons le bouton d'installation une fois que tout est prêt.

Vous avez appris à auditer des sites avec Lighthouse et à mettre en œuvre les bases du fonctionnement hors connexion. Si vous avez rempli les sections facultatives, vous avez également appris à installer des applications Web sur l'écran d'accueil.

Autres ressources

Lighthouse est une technologie Open Source. Vous pouvez le dupliquer, ajouter vos propres tests et signaler des bugs. Lighthouse est également disponible en tant qu'outil de ligne de commande pour intégrer les processus de compilation.

Pour voir tous les ateliers de programmation du cours de formation sur la PWA, consultez l'atelier de bienvenue.