Fermer

juin 27, 2019

Construire un PWA avec Webpack et Workbox

Animation d'une requête réseau allant du navigateur du client à Internet.


Ce didacticiel vous aidera à transformer une application qui ne fonctionne pas hors connexion en un PWA fonctionnant hors connexion et affichant une icône de mise à jour disponible. Vous apprendrez à mettre en cache des éléments avec Workbox, à gérer la mise en cache dynamique et à gérer les mises à jour de votre PWA. Suivez le mouvement et voyez comment vous pouvez également appliquer ces techniques sur votre site web.

Une application Web progressive (PWA) est un site qui utilise une technologie moderne pour offrir des expériences similaires à celles d'une application sur le Web. C’est un terme générique pour désigner les nouvelles technologies telles que le «manifeste des applications Web», le «prestataire de services», etc. Lorsqu'elles sont réunies, ces technologies vous permettent d'offrir une expérience utilisateur rapide et attrayante avec votre site Web.

Cet article est un didacticiel pas à pas permettant d'ajouter un technicien de service à un site Web existant d'une page. Le technicien de service vous permettra de faire fonctionner votre site Web hors connexion tout en informant également vos utilisateurs des mises à jour de votre site. Notez que ceci est basé sur un petit projet fourni avec Webpack. Nous allons donc utiliser le plug-in Workbox Webpack ( Workbox v4 ).

Utiliser un outil pour générer votre prestataire de services est le approche recommandée car elle vous permet de gérer votre cache efficacement. Nous allons utiliser Workbox – un ensemble de bibliothèques qui facilitent la génération de votre code de prestataire de services – pour générer notre prestataire de services dans ce didacticiel.

Selon votre projet, vous pouvez utiliser Workbox en trois parties. Différentes manières:

  1. Une interface de ligne de commande est disponible pour vous permettre d'intégrer un poste de travail à n'importe quelle application.
  2. Un module Node.js est également disponible. boîte de travail dans n'importe quel outil de construction de noeud tel que gulp ou grunt;
  3. Un plugin Webpack est disponible, ce qui vous permet de s'intégrer facilement à un projet construit avec Webpack.

Webpack est un module. bundler. Pour simplifier, vous pouvez le considérer comme un outil permettant de gérer vos dépendances JavaScript. Il vous permet d'importer du code JavaScript depuis des bibliothèques et de regrouper votre JavaScript dans un ou plusieurs fichiers.

Pour commencer, clonez le référentiel suivant sur votre ordinateur:

 git clone git@github.com: jadjoubran / workbox- tutorial-v4.git
cd workbox-tutorial-v4
npm installer
npm run dev

Ensuite, accédez à http: // localhost: 8080 / . Vous devriez pouvoir voir l'application de devise que nous allons utiliser tout au long de ce didacticiel:

 Capture d'écran de l'application de devise que nous construisons dans cet article.
"Monnaies" est un PWA qui répertorie les frais de conversion des devises contre l'euro (€) devise. ( Grand aperçu )

Commencez par un shell d'application

Le shell d'application (ou "app shell") est un modèle inspiré de Native Apps. Cela aidera à donner à votre application une apparence plus native. Il fournit simplement à l'application une présentation et une structure sans aucune donnée – un écran de transition destiné à améliorer l'expérience de chargement de votre application Web.

Voici quelques exemples de shells d'application issus d'applications natives:

 Google Inbox App Shell
Shell de l'application Google Inbox: quelques millisecondes avant le chargement des e-mails dans le shell de l'application. ( Grand aperçu )
 App Shell natif de Twitter
Application native de Twitter sous Android: Coquille d’application affichant la barre de navigation, les onglets et le chargeur. ( Grand aperçu )

Et voici des exemples de coquilles d'application de PWA:

 App Shell du Twitter de PWA
Le shell d'application de PWA de Twitter ( Grand aperçu )
 Application Shell du PWA de Flipkart
Le shell d'application du PWA de Flipkart ( Grand aperçu )

Les utilisateurs apprécient l'expérience de chargement de shells d'application parce qu'ils méprisent les écrans vierges. Un écran vide donne à l'utilisateur le sentiment que le site Web ne se charge pas. Ils se sentent comme si le site Web était bloqué.

Les obus d'application tentent de peindre la structure de navigation de l'application le plus rapidement possible, comme la barre de navigation, la barre d'onglets et un chargeur indiquant que le contenu que vous avez affiché est affiché. demandé est en cours de chargement.

Comment créer un shell d'application?

Le motif de shell d'application accorde la priorité au chargement du code HTML, CSS et JavaScript qui sera rendu en premier. Cela signifie que nous devons accorder la priorité absolue à ces ressources et, par conséquent, vous devez mettre ces ressources en ligne. Donc, pour construire un shell d’application, vous devez simplement insérer les codes HTML, CSS et JavaScript responsables du shell de l’application. Bien sûr, vous ne devez pas tout aligner, mais plutôt rester dans une limite d'environ 30 à 40 Ko.

Vous pouvez voir le shell d'application en ligne dans le index.html . Vous pouvez inspecter le code source en consultant le fichier index.html et vous pouvez le prévisualiser dans le navigateur en supprimant l'élément

dans les outils de développement:

 Devises PWA App Shell avec navbar & loader
L'App Shell que nous construisons dans cet article. ( Grand aperçu )

Est-ce que cela fonctionne hors ligne?

Simulons une mise hors ligne! Ouvrez DevTools, accédez à l’onglet Réseau et cochez la case "Hors ligne". Lorsque vous rechargerez la page, vous constaterez que nous obtiendrons la page hors connexion du navigateur.

 Page d’erreur du navigateur en mode hors connexion
La demande d’accès à la page d’accueil a échoué, ce qui est évidemment le résultat. ( Grand aperçu )

C’est parce que la demande initiale de / (qui chargera le fichier index.html ) échouera car Internet est hors ligne. Le seul moyen pour nous de remédier à cette défaillance de la requête consiste à faire appel à un technicien de maintenance.

Visualisons la requête sans technicien de maintenance:

 Animation d'une requête réseau allant du navigateur du client à Internet.
La requête réseau va du navigateur à Internet et retour. (Icônes de flaticon.com ) ( Grand aperçu )

Un prestataire de services est un proxy réseau programmable, ce qui signifie qu'il se situe entre votre page Web et Internet. Cela vous permet de contrôler les requêtes réseau entrantes et sortantes.

 Animation d'une requête réseau interceptée par le technicien de service.
La requête réseau est interceptée par le technicien de service. (Icônes de flaticon.com ) ( Aperçu grand )

Cela est utile car nous pouvons maintenant réacheminer cette demande échouée vers la mémoire cache (en supposant que nous ayons le contenu dans

 Animation d’une requête réseau interceptée par le prestataire de services et redirigée vers la mémoire cache.
La requête réseau est redirigée vers la mémoire cache quand elle existe déjà dans la mémoire cache. (Icônes de flaticon.com ) ( Grand aperçu )

Un travailleur de service est également un type de travailleur Web, ce qui signifie qu'il est séparé de votre page principale et qu'il ne fonctionne pas. avoir accès à l'objet du document du document ou du document .

Précachez le shell d'application

Pour que notre application fonctionne en mode hors connexion, nous allons commencer par fixer le app shell.

Commençons donc par installer le plugin Webpack Workbox:

 npm install --save-dev workbox-webpack-plugin

Ensuite, nous allons ouvrir notre fichier index.js et enregistrer le technicien:

 if ("serviceWorker" dans le navigateur) {
window.addEventListener ("load", () => {
navigator.serviceWorker.register ("/ sw.js");
})
}

Ensuite, ouvrez le fichier webpack.config.js et configurons le plug-in Workbox Webpack:

 // ajoute en haut de la page
const WorkboxWebpackPlugin = require ("plug-in de workbox-webpack");

// ajoute à l'intérieur du tableau de plugins:
plugins: [
…
, new WorkboxWebpackPlugin.InjectManifest({
  swSrc: "./src/src-sw.js",
  swDest: "sw.js"
})
]

Ceci demandera à Workbox d'utiliser notre fichier ./src / src-sw.js comme base. Le fichier généré s'appellera sw.js et sera placé dans le dossier dist .

Créez ensuite un ./ src / src-sw.js fichier au niveau racine et écrivez ce qui suit à l'intérieur:

 workbox.precaching.precacheAndRoute (self .__ precacheManifest);

Note : La variable self .__ precacheManifest sera importée d'un fichier qui sera généré dynamiquement par la boîte de travail.

Vous êtes prêt maintenant. pour construire votre code avec npm run build et Workbox générera deux fichiers dans le dossier dist :

  • precache-manifest.66cf63077c7e4a70ba741ee9e6a8da29.js [1965907] [1965907] sw.js

Le sw.js importe la boîte de travail de CDN ainsi que le precache-manifest. [chunkhash] .js .

 // precache-manifeste. [chunkhash] fichier .js
self .__ precacheManifest = (self .__ precacheManifest || []). concat ([
  
    "revision": "ba8f7488757693a5a5b1e712ac29cc28",
    "url": "index.html"
  },
  
    "url": "main.49467c51ac5e0cb2b58e.js"
  
]);

Le manifeste de pré-cache répertorie les noms des fichiers traités par webpack et qui se retrouvent dans votre dossier dist . Nous allons utiliser ces fichiers pour les mettre en cache dans le navigateur. Cela signifie que lorsque votre site Web se charge pour la première fois et enregistre l'agent de service, il stockera ces actifs dans un cache afin qu'ils puissent être utilisés la prochaine fois.

Vous pouvez également remarquer que certaines entrées ont une "révision", tandis que d'autres ne le font pas. t. C’est parce que la révision peut parfois être déduite du chunkhash du nom de fichier. Par exemple, examinons de plus près le nom du fichier main.49467c51ac5e0cb2b58e.js . Il a une révision dans le nom du fichier, qui est le chunkhash 49467c51ac5e0cb2b58e .

Cela permet à Workbox de comprendre le moment où vos fichiers sont modifiés, de sorte qu'il ne nettoie ou ne mette à jour que les fichiers modifiés. tout le cache à chaque fois que vous publiez une nouvelle version de votre service worker.

La première fois que vous chargez la page, le service maintenance sera installé. Vous pouvez le voir dans DevTools. Tout d'abord, le fichier sw.js est demandé, qui demande ensuite tous les autres fichiers. Elles sont clairement identifiées par l’icône représentant une roue dentée.

 Capture d’écran de l’onglet Réseau DevTools lors de l’installation du prestataire de services.
Les demandes signalées par l’icône sont des demandes initiées par le prestataire de services. ( Grand aperçu )

Donc, Workbox s’initialisera et mettra en cache tous les fichiers qui se trouvent dans le manifeste de pré-cache. Il est important de vérifier que vous n'avez aucun fichier inutile dans le fichier precache-manifest tel que les fichiers .map ou les fichiers ne faisant pas partie du shell de l'application. 19659003] Dans l'onglet Réseau, nous pouvons voir les demandes provenant du service worker. Et maintenant, si vous essayez de vous déconnecter, le shell de l'application est déjà précaché, de sorte que cela fonctionne même si nous sommes hors ligne!

 Capture d'écran de l'onglet Dev Tools Network montrant l'échec des appels d'API.
Les appels d'API échouent lorsque nous passons en mode hors connexion. ( Grand aperçu )

Cache Dynamic Routes

Avez-vous remarqué que, lorsque nous sommes passés hors ligne, le shell de l'application fonctionne, mais pas nos données? C’est parce que ces appels d’API ne font pas partie du shell d’application précachée précachée . En l'absence de connexion Internet, ces demandes échoueront et l'utilisateur ne pourra pas voir les informations sur la devise.

Cependant, ces demandes ne peuvent pas être précachées, car leur valeur provient d'une API. De plus, lorsque vous commencez à avoir plusieurs pages, vous ne souhaitez pas mettre en cache toutes les demandes d’API en une seule fois. Au lieu de cela, vous souhaitez les mettre en cache lorsque l'utilisateur visite cette page.

Nous les appelons «données dynamiques». Elles incluent souvent des appels d’API ainsi que des images et autres éléments demandés lorsqu’un utilisateur effectue certaines actions sur votre site Web (par exemple, lorsqu'il navigue vers une nouvelle page).

Vous pouvez les mettre en cache à l’aide du module de routage de Workbox. Voici comment:

 // ajouter src / src-sw.js
workbox.routing.registerRoute (
  /https://api.exchangeratesapi.io/latest/,
  new workbox.strategies.NetworkFirst ({
    cacheName: "monnaies",
    plugins: [
      new workbox.expiration.Plugin ({
        maxAgeSeconds: 10 * 60 // 10 minutes
      })
    
  })
)

Ceci va configurer la mise en cache dynamique pour toute URL de requête qui correspond à l'URL https://api.exchangeratesapi.io/latest .

La stratégie de mise en cache que nous avons utilisée ici s'appelle . NetworkFirst ;

  1. CacheFirst
  2. StaleWhileRevalidate

CacheFirst va d'abord le rechercher dans la cache. S'il n'est pas trouvé, il l'obtiendra du réseau. StaleWhileRevalidate ira au réseau et au cache en même temps. Renvoyer la réponse du cache à la page (en arrière-plan), il utilisera la nouvelle réponse du réseau pour mettre à jour le cache lors de sa prochaine utilisation.

Pour notre cas d'utilisation, nous avons dû utiliser NetworkFirst parce que nous avons affaire à des taux de change qui changent très souvent. Cependant, lorsque l'utilisateur se déconnecte, on peut au moins lui montrer les tarifs tels qu'ils étaient il y a 10 minutes - c'est pourquoi nous avons utilisé le plug-in d'expiration avec le paramètre maxAgeSeconds défini sur 10 * 60 secondes.

Gérer les mises à jour des applications

Chaque fois qu'un utilisateur charge votre page, le navigateur exécute le code navigator.serviceWorker.register même si l'agent de service est déjà installé et en cours d'exécution. Cela permet au navigateur de détecter s’il existe une nouvelle version du service worker. Lorsque le navigateur constate que le fichier n'a pas changé, il ignore simplement l'appel d'enregistrement. Une fois que ce fichier a été modifié, le navigateur a compris qu'il existe une nouvelle version du service worker et il installe donc le nouveau service worker parallèlement au service worker en cours d'exécution .

Cependant, il s'arrête en même temps que le . ] phase installée / en attente car un seul technicien peut être activé à la fois.

 Cycle de vie d’un technicien: analysé, installé / en attente, activé et redondant
Un cycle de vie simplifié ouvrier de service ( Grand aperçu )

Ce n'est que lorsque toutes les fenêtres du navigateur contrôlées par l'ancien ouvrier de service sont installées que l'activation du nouvel ouvrier de service devient sans danger.

Vous pouvez également contrôler manuellement cela en appelant skipWaiting () (ou self.skipWaiting () puisque self correspond au contexte global d'exécution du prestataire de services). Cependant, la plupart du temps, vous ne devriez le faire qu'après avoir demandé à l'utilisateur s'il souhaitait obtenir la dernière mise à jour.

Heureusement, la fenêtre de travail nous aide à atteindre cet objectif. C’est une nouvelle bibliothèque de fenêtres introduite dans Workbox v4 dans le but de simplifier les tâches courantes côté fenêtre.

Commençons par l’installer avec les éléments suivants:

 npm install workbox-window

Ensuite, importez la boîte de travail en haut du fichier index.js :

 import {Workbox} à partir de "workbox-window";

Ensuite, nous remplacerons notre code d’enregistrement par le suivant:

 if ("serviceWorker" dans le navigateur) {
  window.addEventListener ("load", () => {
      const wb = new Workbox ("/ sw.js");
    
wb.register ();
  });

}

Nous allons ensuite trouver le bouton de mise à jour portant l'ID app-update et écouter l'événement workbox-waiting :

 // ajouter avant le wb.register ()
const updateButton = document.querySelector ("# app-update");
// Se déclenche lorsque le technicien de service inscrit est installé mais attend pour l'activer.
wb.addEventListener ("waiting", event => {
    updateButton.classList.add ("show");
    updateButton.addEventListener ("click", () => {
    // Configurez un écouteur qui rechargera la page dès que le prestataire de service précédemment en attente aura pris le contrôle.
    wb.addEventListener ("controlling", événement => {
        window.location.reload ();
    });

    // Envoyer un message demandant au technicien de service d’attendre l’attente.
    // Ceci déclenchera le gestionnaire d'événements `controlling` ci-dessus.
    wb.messageSW ({type: "SKIP_WAITING"});
    });
});

Ce code affichera le bouton de mise à jour lorsqu’il y aura une nouvelle mise à jour (ainsi lorsque le technicien sera en attente) et enverra un message SKIP_WAITING au technicien.

besoin de mettre à jour le fichier d'opérateur de service et de gérer l'événement SKIP_WAITING tel qu'il appelle l'événement skipWaiting :

 // ajouter in src-sw.js
addEventListener ("message", event => {
  if (event.data && event.data.type === "SKIP_WAITING") {
    skipWaiting ();
  
});

Maintenant, lancez npm run dev puis rechargez la page. Allez dans votre code et mettez à jour le titre de la barre de navigation en «Navbar v2». Rechargez à nouveau la page et vous devriez pouvoir voir l'icône de mise à jour.

Enveloppant

Notre site web fonctionne maintenant hors connexion et permet d'avertir l'utilisateur des nouvelles mises à jour. Gardez toutefois à l'esprit que le facteur le plus important lors de la création d'un PWA est l'expérience utilisateur. Concentrez-vous toujours sur la création d’expériences faciles à utiliser par vos utilisateurs. En tant que développeurs, nous avons tendance à être trop enthousiastes face à la technologie et finissons souvent par oublier nos utilisateurs.

Si vous souhaitez aller plus loin, vous pouvez ajouter un manifeste d'application Web qui permettra à vos utilisateurs d'ajouter le site à leur écran d'accueil. Et si vous souhaitez en savoir plus sur Workbox, vous pouvez trouver la documentation officielle sur le site Web Workbox .

Pour en savoir plus sur SmashingMag:

 Smashing Editorial ] (dm, yk, il)



Source link