aboutsummaryrefslogtreecommitdiff
path: root/files/fr/web/api/service_worker_api
diff options
context:
space:
mode:
Diffstat (limited to 'files/fr/web/api/service_worker_api')
-rw-r--r--files/fr/web/api/service_worker_api/index.html290
-rw-r--r--files/fr/web/api/service_worker_api/using_service_workers/index.html522
2 files changed, 812 insertions, 0 deletions
diff --git a/files/fr/web/api/service_worker_api/index.html b/files/fr/web/api/service_worker_api/index.html
new file mode 100644
index 0000000000..dc15a4f63a
--- /dev/null
+++ b/files/fr/web/api/service_worker_api/index.html
@@ -0,0 +1,290 @@
+---
+title: Service Worker API
+slug: Web/API/Service_Worker_API
+tags:
+ - API
+ - Chargement
+ - Service Workers
+ - Workers
+ - hors-ligne
+translation_of: Web/API/Service_Worker_API
+---
+<div>
+<p>{{ServiceWorkerSidebar}}</p>
+
+<p>{{ SeeCompatTable() }}</p>
+
+<p class="summary">Les service workers jouent essentiellement le rôle de serveurs proxy placés entre une application web, et le navigateur ou le réseau (lorsque disponible.) Ils sont destinés (entre autres choses) à permettre la création d'expériences de navigation déconnectée efficaces, en interceptant les requêtes réseau et en effectuant des actions appropriées selon que le réseau est disponible et que des ressources mises à jour sont à disposition sur le serveur. Ils permettront aussi d'accéder aux APIs de notifications du serveur (push) et de synchronisation en arrière-plan.</p>
+</div>
+
+<h2 id="Service_worker_concepts_et_usage">Service worker, concepts et usage</h2>
+
+<p>Un service worker est un <a href="https://developer.mozilla.org/en-US/docs/Web/API/Worker">worker</a> événementiel enregistré auprès d'une origine et d'un chemin. Il prend la forme d'un fichier JavaScript qui peut contrôler la page ou le site web auquel il est associé, en interceptant et en modifiant la navigation et les requêtes de ressources, et en mettant en cache les ressources selon une granularité très fine pour vous donner une maîtrise complète de la manière dont doit se comporter votre application dans certaines situations (l'une des plus évidentes étant l'indisponibilité du réseau.)</p>
+
+<p>Un service worker fonctionne dans le contexte d'un worker : il n'a donc pas d'accès au DOM, et s'exécute dans une tâche différente de celle du script principal de votre application, ainsi il est non-bloquant. Il est conçu pour être totalement asynchrone; en conséquence, des APIs telles que <a href="/fr/docs/Web/API/XMLHttpRequest">XHR</a> en synchrone et <a href="/fr/docs/Web/API/Web_Storage_API">localStorage</a> ne peuvent pas être utilisées au sein d'un service worker.</p>
+
+<p>Les service workers fonctionnent uniquement sur HTTPS, pour des raisons de sécurité. Laisser des requêtes réseau modifiées sans défense face aux attaques de l'homme du milieu est une bien mauvaise chose.</p>
+
+<div class="note">
+<p><strong>Remarque </strong>: les service workers ont rallié à eux des tentatives précédemment effectuées dans les mêmes domaines comme l'API <a class="external" href="http://alistapart.com/article/application-cache-is-a-douchebag">AppCache</a> parce qu'ils ne présument pas de ce que vous essayez de faire et ainsi s'interrompent quand ces suppositions ne sont pas tout à fait exactes; tout peut faire l'objet d'un contrôle d'une granularité très fine.</p>
+</div>
+
+<div class="note">
+<p><strong>Remarque </strong>: les service workers font un usage intensif des <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise" lang="fr">promesses</a>, comme généralement ils sont en attente de réponses, auxquelles ils réagissent alors différemment en cas de succès ou en cas d'erreur. L'architecture des promesses est idéale dans ces situations.</p>
+</div>
+
+<h3 id="Enregistrement">Enregistrement</h3>
+
+<p>Un service worker est d'abord enregistré en utilisant la méthode {{domxref("ServiceWorkerContainer.register()")}}. En cas de succès, votre service worker sera téléchargé par le client et tentera l'installation/l'activation (voir ci-dessous) des URLs accédées par l'utilisateur au sein du domaine complet, ou bien au sein d'un sous-ensemble spécifié par vos soins.</p>
+
+<h3 id="Télécharger_installer_et_activer">Télécharger, installer et activer</h3>
+
+<p>A cette étape, votre service worker observera le cycle de vie suivant :</p>
+
+<ol>
+ <li>Téléchargement</li>
+ <li>Installation</li>
+ <li>Activation</li>
+</ol>
+
+<p>Le service worker est immédiatement téléchargé lorsqu'un utilisateur accède pour la première fois à une page ou à un site contrôlé par un service worker.</p>
+
+<p>Après cela, il est téléchargé toutes les 24 heures environ. Il *peut* être téléchargé plus fréquemment, mais il <strong>doit </strong>être téléchargé toutes les 24 heures pour s'assurer que des scripts défectueux ne constitueraient pas une nuisance durable.</p>
+
+<p>Une tentative d'installation a lieu lorsque le fichier téléchargé se trouve être nouveau — soit qu'il est différent d'un service worker existant (comparaison bit à bit), soit qu'il s'agit du premier service worker rencontré pour cette page ou ce site.</p>
+
+<p>Si c'est la première fois qu'un service worker est rendu disponible, une tentative d'installation a lieu, puis en cas d'installation avec succès il est activé.</p>
+
+<p>S'il existait déjà un service worker, la nouvelle version est installée en arrière-plan, mais pas encore activée — à cette étape, on parle de <em>worker en attente</em>. Il n'est activé que lorsqu'il n'y a plus aucune page chargée faisant encore usage de l'ancien service worker. Aussitôt qu'il n'y a plus de telles pages chargées, le nouveau service worker est activé (devenant le <em>active worker</em>.)</p>
+
+<p>Vous pouvez guetter l'événement {{domxref("InstallEvent")}}; une action standard consiste à préparer l'usage de votre service worker quand cet événement est lancé, par exemple en créant un cache au moyen de l'API de stockage native, et en y plaçant les ressources dont vous avez besoin pour faire fonctionner de manière déconnectée votre application.</p>
+
+<p>Il y a aussi un événement <code>activate</code>. Lorsque cet événement se produit, c'est généralement le bon moment pour nettoyer les vieux caches et toutes les autres choses associées avec la version précédente de votre service worker.</p>
+
+<p>Votre service worker peut répondre aux requêtes en utilisant l'événement {{domxref("FetchEvent")}}. Vous pouvez modifier la réponse à ces requêtes de la manière que vous souhaitez, en utilisant la méthode {{domxref("FetchEvent.respondWith") }}.</p>
+
+<div class="note">
+<p><strong>Remarque </strong>: Parce que <code>oninstall</code>/<code>onactivate</code> pourraient prendre du temps à s'exécuter, la spec service worker fournit une méthode <code>waitUntil</code> qui, lorsque <code>oninstall</code> ou <code>onactivate</code> sont appelées, passe une promesse. Les événements fonctionnels ne sont pas envoyés au service worker tant que la promesse n'a pas été résolue avec succès.</p>
+</div>
+
+<p>Pour un tutoriel complet qui montre comment réaliser un premier exemple basique, il est conseillé de lire <a href="/fr/docs/Web/API/Service_Worker_API/Using_Service_Workers">Utiliser les Services Workers</a>.</p>
+
+<h2 id="Autres_idées_de_cas_d'utilisation">Autres idées de cas d'utilisation</h2>
+
+<p>Les service workers sont aussi destinés à être utilisés pour des choses telles que :</p>
+
+<ul>
+ <li>Synchronisation de données en arrière-plan</li>
+ <li>Répondre à des requêtes de ressource provenant d'autres origines</li>
+ <li>Recevoir des mises à jour centralisées de données coûteuses à calculer telles que la géolocalisation ou le gyroscope, afin que de nombreuses pages puissent bénéficier du même ensemble de données</li>
+ <li>Compilation côté client et gestion des dépendances de CoffeeScript, less, modules CJS/AMD, etc. pour des besoins de développement</li>
+ <li>Branchements pour des services en arrière-plan</li>
+ <li>Personnalisation de gabarit en fonction de certains schémas d'URL</li>
+ <li>Amélioration des performances, par exemple en pré-chargeant des ressources dont l'utilisateur aura probablement besoin par la suite, comme de nouvelles images lors de la consultation d'un album photo.</li>
+</ul>
+
+<p>À l'avenir, les service workers seront capables de réaliser nombre d'autres tâches utiles au sein d'une plate-forme web, ce qui les rapprochera de la viabilité des applications natives. Il est intéressant de noter que d'autres spécifications peuvent ou commencent à faire usage du contexte des service workers, par exemple :</p>
+
+<ul>
+ <li><a class="external" href="https://github.com/slightlyoff/BackgroundSync">Synchronisation en arrière-plan</a> : démarrer un service worker même lorsqu'aucun utilisateur est sur le site, afin de mettre à jour les caches, etc.</li>
+ <li><a href="/fr/docs/Web/API/Push_API">Réagir à des messages de push </a>: démarrer un service worker pour envoyer aux utilisateurs un message leur signalant qu'un nouveau contenu est disponible.</li>
+ <li>Réagir à une date particulière</li>
+ <li>Enregistrer une géo-localisation</li>
+</ul>
+
+<h2 id="Interfaces">Interfaces</h2>
+
+<dl>
+ <dt>{{domxref("Cache") }}</dt>
+ <dd>Représente le stockage pour le couple d'objets {{domxref("Request")}} / {{domxref("Response")}} qui sont mis en cache comme partie du cycle de vie de {{domxref("ServiceWorker")}}.</dd>
+ <dt>{{domxref("CacheStorage") }}</dt>
+ <dd>Représente le stockage pour les objets {{domxref("Cache")}}. Il fournit un répertoire maître à tous les caches nommés auxquels un {{domxref("ServiceWorker")}} peut accéder et maintient une correspondance de noms avec les objets {{domxref("Cache")}} correspondants.</dd>
+ <dt>{{domxref("Client") }}</dt>
+ <dd>Représente la portée d'un service worker client. Un service worker client est soit un document dans le contexte d'un navigateur ou un {{domxref("SharedWorker")}}, qui est contrôlé par un active worker.</dd>
+ <dt>{{domxref("Clients") }}</dt>
+ <dd>Représente un conteneur pour une liste d'objets {{domxref("Client")}}; la façon principale d'accéder aux clients du service worker actif de l'origine en cours.</dd>
+ <dt>{{domxref("ExtendableEvent") }}</dt>
+ <dd>Étend la durée de vie des événements <code>install</code> et <code>activate</code> envoyés au {{domxref("ServiceWorkerGlobalScope")}} comme partie du cycle de vie d'un service worker. Cela garantit que tout événement fonctionnel (comme {{domxref("FetchEvent")}}) n'est pas envoyé au {{domxref("ServiceWorker")}} avant qu'il ne mette à jour des schémas de base de données, supprime des entrées de cache obsolètes, etc.</dd>
+ <dt>{{domxref("ExtendableMessageEvent") }}</dt>
+ <dd>L'objet événement d'un événement {{event("message_(ServiceWorker)","message")}} déclenché sur un service worker (lorsqu'un message est reçu par le {{domxref("ServiceWorkerGlobalScope")}} à partir d'un autre contexte) — étend la durée de vie de tels événements.</dd>
+ <dt>{{domxref("FetchEvent") }}</dt>
+ <dd>Le paramètre passé au gestionnaire {{domxref("ServiceWorkerGlobalScope.onfetch")}}, l'interface <code>FetchEvent</code> représente une action de recherche qui est envoyée au {{domxref("ServiceWorkerGlobalScope")}} d'un {{domxref("ServiceWorker")}}. Il contient des informations à propos de la requête et de la réponse résultante, et fournit la méthode {{domxref("FetchEvent.respondWith", "FetchEvent.respondWith()")}}, qui nous permet de produire une réponse arbitraire en retour à la page contrôlée.</dd>
+ <dt>{{domxref("InstallEvent") }}</dt>
+ <dd>Le paramètre passé au gestionnaire {{domxref("ServiceWorkerGlobalScope.oninstall", "oninstall")}}, l'interface <code>InstallEvent</code> représente une action d'installation qui est envoyée au {{domxref("ServiceWorkerGlobalScope")}} d'un {{domxref("ServiceWorker")}}. En tant qu'enfant de {{domxref("ExtendableEvent")}}, il garantit que les événements fonctionnels tels que {{domxref("FetchEvent")}} ne sont pas envoyés pendant l'installation. </dd>
+ <dt>{{domxref("Navigator.serviceWorker") }}</dt>
+ <dd>Retourne un objet {{domxref("ServiceWorkerContainer")}}, qui fournit un accès provides à l'enregistrement, la supression, la mise à jour, et la communication avec les objets {{domxref("ServiceWorker")}} pour le <a href="https://html.spec.whatwg.org/multipage/browsers.html#concept-document-window">document associé</a>.</dd>
+ <dt>{{domxref("NotificationEvent") }}</dt>
+ <dd>Le paramètre passé au gestionnaire {{domxref("ServiceWorkerGlobalScope.onnotificationclick", "onnotificationclick")}}, l'interface <code>NotificationEvent</code> représente un événement de notification au clic qui est envoyé au {{domxref("ServiceWorkerGlobalScope")}} d'un {{domxref("ServiceWorker")}}.</dd>
+ <dt>{{domxref("PeriodicSyncEvent")}} {{non-standard_inline}}</dt>
+ <dd>
+ <p>Le paramètre passé au gestionnaire sync, l'interface SyncEvent représente une action de synchronisation périodique qui est envoyée au  {{domxref("ServiceWorkerGlobalScope")}} d'un ServiceWorker. </p>
+ </dd>
+ <dt>{{domxref("PeriodicSyncManager")}} {{non-standard_inline}}</dt>
+ <dd>Fournit une interface pour l'enregistrement et la récupération des objets {{domxref("PeriodicSyncRegistration")}}.</dd>
+ <dt>{{domxref("PeriodicSyncRegistration")}} {{non-standard_inline}}</dt>
+ <dd>Fournit un objet pour la gestion d'une synchronisation périodique en arrière-plan. </dd>
+ <dt>{{domxref("ServiceWorker") }}</dt>
+ <dd>Représente un service worker. De multiples contextes de navigation (e.g. des pages, des workers, etc.) peuvent être associés au même objet <code>ServiceWorker</code>.</dd>
+ <dt>{{domxref("ServiceWorkerContainer") }}</dt>
+ <dd>Fournit un objet représentant le service worker comme une unité d'ensemble dans l'éco-système du réseau, en incluant des facilités d'enregistrement, de désinscription et de mise à jour des service workers, et d'accès à l'état des service workers et de leur enregistrement.</dd>
+ <dt>{{domxref("ServiceWorkerGlobalScope") }}</dt>
+ <dd>Représente le contexte global d'exécution d'un service worker.</dd>
+ <dt>{{domxref("ServiceWorkerMessageEvent")}}</dt>
+ <dd>Contient des informations à propos d'un événement envoyé à la cible d'un {{domxref("ServiceWorkerContainer")}}. </dd>
+ <dt>{{domxref("ServiceWorkerRegistration") }}</dt>
+ <dd>Représente l'enregistrement d'un service worker.</dd>
+ <dt>{{domxref("SyncEvent")}} {{non-standard_inline}}</dt>
+ <dd>
+ <p>Le paramètre passé au gestionnaire sync, l'interface SyncEvent représente une action de synchronisation qui est envoyée au {{domxref("ServiceWorkerGlobalScope")}} d'un ServiceWorker. </p>
+ </dd>
+ <dt>{{domxref("SyncManager")}} {{non-standard_inline}}</dt>
+ <dd>Fournit une interface pour l'enregistrement et la récupération des objets {{domxref("SyncRegistration")}}.</dd>
+ <dt>{{domxref("SyncRegistration")}} {{non-standard_inline}}</dt>
+ <dd>Fournit un objet pour la gestion d'une synchronisation en arrière-plan.</dd>
+ <dt>{{domxref("WindowClient") }}</dt>
+ <dd>Représente la portée d'un service worker client qui est un document dans le contexte d'un navigateur, contrôlé par un active worker. C'est un type spécial d'objet {{domxref("Client")}}, avec des propriété et des méthodes supplémentaires.</dd>
+</dl>
+
+<h2 id="Spécifications">Spécifications</h2>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">Spécification</th>
+ <th scope="col">Statut</th>
+ <th scope="col">Commentaire</th>
+ </tr>
+ <tr>
+ <td>{{SpecName('Service Workers', '')}}</td>
+ <td>{{Spec2('Service Workers')}}</td>
+ <td>Définition initiale.</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Compatibilité_des_navigateurs">Compatibilité des navigateurs</h2>
+
+<div>{{ CompatibilityTable() }}</div>
+
+<div id="compat-desktop">
+<table class="compat-table">
+ <tbody>
+ <tr>
+ <th>Fonctionnalité</th>
+ <th>Chrome</th>
+ <th>Firefox (Gecko)</th>
+ <th>Internet Explorer</th>
+ <th>Opera</th>
+ <th>Safari (WebKit)</th>
+ </tr>
+ <tr>
+ <td>Support basique</td>
+ <td>{{CompatChrome(40.0)}}</td>
+ <td>{{ CompatGeckoDesktop("44.0") }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>24</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>install/activate events</td>
+ <td>{{ CompatChrome(40.0) }}</td>
+ <td>{{ CompatGeckoDesktop("44.0") }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatVersionUnknown() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>fetch event/request/<br>
+ <code>respondWith()</code></td>
+ <td>{{CompatChrome(40.0)}}</td>
+ <td>{{ CompatGeckoDesktop("44.0") }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>caches/cache</td>
+ <td>
+ <p class="p1">{{CompatChrome(42.0)}}</p>
+ </td>
+ <td>{{ CompatGeckoDesktop("39.0") }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+<div id="compat-mobile">
+<table class="compat-table">
+ <tbody>
+ <tr>
+ <th>Fonctionnalité</th>
+ <th>Android</th>
+ <th>Chrome for Android</th>
+ <th>Firefox Mobile (Gecko)</th>
+ <th>Firefox OS</th>
+ <th>IE Phone</th>
+ <th>Opera Mobile</th>
+ <th>Safari Mobile</th>
+ </tr>
+ <tr>
+ <td>Support basique</td>
+ <td> </td>
+ <td>{{CompatChrome(40.0)}}</td>
+ <td>{{ CompatGeckoMobile("44.0") }}</td>
+ <td>{{ CompatVersionUnknown }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatVersionUnknown() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td> install/activate events</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{CompatChrome(40.0)}}</td>
+ <td>{{ CompatGeckoMobile("44.0") }}</td>
+ <td>{{ CompatVersionUnknown }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatVersionUnknown() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>fetch event/request/<br>
+ <code>respondWith()</code></td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{CompatChrome(40.0)}}</td>
+ <td>{{ CompatGeckoMobile("44.0") }}</td>
+ <td>{{ CompatVersionUnknown }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>caches/cache</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{CompatChrome(40.0)}}</td>
+ <td>{{ CompatGeckoMobile("39.0") }}</td>
+ <td>{{ CompatVersionUnknown }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+<div class="note">
+<p><strong>Remarque </strong>: pour une raison de rétrocompatibilité, vous pourriez choisir d'utiliser à la fois les service workers et AppCache sur la même application web pour réaliser des choses équivalentes (si AppCache permet de les réaliser, bien entendu.) Dans une telle situation, il y aura les navigateurs qui ne supportent pas les Service Workers et qui utiliseront alors AppCache, et ceux qui ignoreront AppCache au profit du service worker.</p>
+</div>
+
+<h2 id="Voir_aussi">Voir aussi</h2>
+
+<ul>
+ <li><a class="external" href="https://serviceworke.rs">ServiceWorker Cookbook</a></li>
+ <li><a href="/fr/docs/Web/API/Service_Worker_API/Using_Service_Workers" lang="fr">Utilisation des Service Workers</a></li>
+ <li><a class="external" href="https://github.com/mdn/sw-test">Exemple basique de Service workers</a></li>
+ <li><a class="external" href="https://jakearchibald.github.io/isserviceworkerready/">Is ServiceWorker ready?</a></li>
+ <li><a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise">Promises</a></li>
+ <li><a href="/fr/docs/Utilisation_des_web_workers">Utilisation des web workers</a></li>
+</ul>
diff --git a/files/fr/web/api/service_worker_api/using_service_workers/index.html b/files/fr/web/api/service_worker_api/using_service_workers/index.html
new file mode 100644
index 0000000000..be23121f08
--- /dev/null
+++ b/files/fr/web/api/service_worker_api/using_service_workers/index.html
@@ -0,0 +1,522 @@
+---
+title: Utiliser les Service Workers
+slug: Web/API/Service_Worker_API/Using_Service_Workers
+tags:
+ - Guide
+ - Service
+ - ServiceWorker
+ - Workers
+ - basics
+translation_of: Web/API/Service_Worker_API/Using_Service_Workers
+---
+<p>{{ServiceWorkerSidebar}}</p>
+
+<p>{{ SeeCompatTable() }}</p>
+
+<div class="summary">
+<p>Cet article fournit des informations pour bien débuter avec les service workers, en présentant une architecture de base, l'inscription d'un service worker, l'installation et l'activation d'un processus pour un nouveau service worker, la mise à jour d'un service worker, le contrôle du cache et la personnalisation des réponses, le tout dans le contexte d'une application de base disponible en mode déconnecté.</p>
+</div>
+
+<h2 id="Le_préambule_aux_Service_Workers">Le préambule aux Service Workers</h2>
+
+<p>La perte de connexion est un problème majeur auquel sont confrontés les utilisateurs du web depuis des années. La meilleure application web au monde produirait un bien mauvais effet si vous ne pouviez pas la télécharger. Il y a eu de nombreuses tentatives pour mettre en place des technologies susceptibles de résoudre ce problème, comme le montre notre page <a href="/fr/Apps/Build/Hors-ligne">Offline</a>, et certains problèmes ont été résolus. Mais le problème principal reste l'absence d'un mécanisme de contrôle global pour la mise en cache des ressources et la personnalisation des requêtes réseau.<br>
+ <br>
+ La première tentative— AppCache — semblait être une bonne idée parce qu'elle permettait de spécifier les ressources à mettre en cache de manière très simple. Cependant, elle faisait beaucoup de suppositions sur la manière de le mettre en place et échouait implacablement si votre application ne se pliait pas exactement à ces suppositions. Lisez <a href="http://alistapart.com/article/application-cache-is-a-douchebag">Application Cache is a Douchebag</a> de Jake Archibald pour plus de détails.</p>
+
+<div class="note">
+<p><strong>Remarque </strong>: à partir de Firefox 44, lorsque <a href="/fr/docs/Web/HTML/Utiliser_Application_Cache">AppCache</a> est utilisé pour fournir un support déconnecté à une page, un message d'avertissement est alors affiché dans la console pour signaler aux développeurs d'utiliser plutôt les <a href="/fr/docs/Web/API/Service_Worker_API/Using_Service_Workers">Service workers</a> ({{bug("1204581")}}.)</p>
+</div>
+
+<p>Les service workers devraient finalement résoudre ces problèmes. La syntaxe du service Worker est plus complexe que celle de l'AppCache, mais en contrepartie vous pouvez utiliser JavaScript pour contrôler les comportements induits par votre cache local avec une granularité beaucoup plus fine, vous permettant ainsi d'adresser ce problème et beaucoup d'autres. Avec l'aide d'un Service Worker, vous pouvez facilement configurer une application pour d'abord utiliser des ressources mises en cache, fournissant ainsi une première expérience par défaut même en mode déconnecté, avant de récupérer davantage de données depuis le réseau (principe connu généralement sous le nom de <a href="http://offlinefirst.org/">Offline First</a>). Cette façon de faire est déjà disponible avec les applications natives, ce qui est l'une des raisons principales de la préférence accordée à ces applications plutôt qu'aux applications web.</p>
+
+<h2 id="Préparatifs_aux_Service_Workers">Préparatifs aux Service Workers</h2>
+
+<p>De nombreuses fonctionnalités des service workers sont désormais disponibles par défaut dans les plus récentes versions des navigateurs qui les supportent. Cependant, si vous constatez que le code de la démo ne fonctionne pas dans votre version actuelle, vous pourriez avoir besoin d'activer une configuration :</p>
+
+<ul>
+ <li><strong>Firefox Nightly </strong>: rendez-vous sur <code>about:config</code> et configurer  <code>dom.serviceWorkers.enabled</code> à true; redémarrer le navigateur.</li>
+ <li><strong>Chrome Canary </strong>: rendez-vous sur <code>chrome://flags</code> et activer <code>experimental-web-platform-features</code>; redémarrer le navigateur (à noter que certaines fonctionnalités sont désormais activées par défaut dans Chrome.)</li>
+ <li><strong>Opera </strong>: rendez-vous sur <code>opera://flags</code> et activer <code>Support for ServiceWorker</code>; redémarrer le navigateur.</li>
+</ul>
+
+<p>Vous aurez aussi besoin de servir votre code via HTTPS — les Service Workers sont contraints à s'exécuter au travers d'HTTPS pour des raisons de sécurité. GitHub est donc un bon endroit pour héberger des expérimentations, puisqu'il supporte HTTPS. Et pour faciliter le développement en local, le <strong>localhost </strong>est considéré comme une origine sécurisée.</p>
+
+<h2 id="Architecture_de_base">Architecture de base</h2>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/8241/flowchart-production-version.png" style="float: right; height: 600px; margin-left: 20px; width: 300px;"></p>
+
+<p>Avec les service workers, les étapes suivantes sont généralement observées pour une configuration simple :</p>
+
+<ol>
+ <li>L'URL du service worker URL est récupérée et enregistrée via {{domxref("serviceWorkerContainer.register()")}}.</li>
+ <li>En cas de succès, le service worker est exécuté dans un {{domxref("ServiceWorkerGlobalScope") }}; c'est en gros une sorte de contexte de worker spécial, fonctionnant hors du fil d'exécution du script principal, sans accès au DOM.</li>
+ <li>Le service worker est désormais prêt à traiter des événements.</li>
+ <li>Une tentative d'installation du worker a lieu lorsque les pages contrôlées par le service worker sont accédées par la suite. Un événement install est toujours le premier envoyé à un service worker (ça peut être le point de départ pour procéder au remplissage d'une base IndexedDB, et à la mise en cache de ressources du site). C'est tout à fait le même type de procédure que l'installation d'une application native ou Firefox OS — en mettant l'ensemble à disposition pour un usage déconnecté.</li>
+ <li>Lorsque le gestionnaire <code>oninstall</code> se termine, on considère que le service worker est installé.</li>
+ <li>L'étape suivante est l'activation. Lorsque le service worker est installé, il reçoit alors un événement activate. L'utilité première de <code>onactivate</code> est de nettoyer les ressources utilisées dans les versions précédentes du script du Service Worker.</li>
+ <li>Le Service Worker contrôle désormais les pages, mais seulement celles ouvertes après que le <code>register()</code> ait réussi. Ainsi un document à sa création s'accompagne ou non d'un Service Worker et conserve cet état tout au long de sa durée de vie. Ainsi les documents devront être rechargés pour réellement être contrôlés.</li>
+</ol>
+
+<h3 id="Promesses">Promesses</h3>
+
+<p><a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise">Les Promesses</a> sont un puissant mécanisme pour exécuter des opérations asynchrones, dont le succès de l'une dépend du succès de l'autre. Ce mécanisme est au coeur du fonctionnement des service workers.<br>
+ <br>
+ Les promesses peuvent effectuer bien des choses, mais pour le moment il suffit de savoir que si une promesse est retournée, on peut lui attacher un <code>.then()</code> et inclure des fonctions de rappel en cas de succès, d'échec, etc., ou bien un <code>.catch()</code> et inclure une fonction de rappel en cas d'échec.</p>
+
+<p>Comparons la structure d'une fonction classique de rappel synchrone à la promesse asynchrone équivalente.</p>
+
+<h4 id="sync">sync</h4>
+
+<pre class="brush: js notranslate">try {
+ var value = myFunction();
+ console.log(value);
+} catch(err) {
+ console.log(err);
+}</pre>
+
+<h4 id="async">async</h4>
+
+<pre class="brush: js notranslate">myFunction().then(function(value) {
+ console.log(value);
+ }).catch(function(err) {
+ console.log(err);
+});</pre>
+
+<p>Dans le premier exemple, on doit attendre que l'exécution de <code>myFunction()</code> retourne <code>value</code> avant de poursuivre l'exécution de tout autre code. Dans le second exemple, <code>myFunction()</code> retourne une promesse pour <code>value</code>, ainsi le reste du code peut continuer à s'exécuter. Lorsque la promesse est résolue, le code à l'intérieur de <code>then</code> s'exécutera, de manière asynchrone.<br>
+ <br>
+ Qu'en est-il sur un exemple concret — qu'en est-il si, lors d'un chargement dynamique d'images, on veut être sûre qu'elles soient bien chargées avant de les afficher ? C'est une démarche standard à adopter, mais parfois problématique. On peut utiliser <code>.onload</code> pour n'afficher l'image qu'après qu'elle soit chargée, mais qu'en est-il des événements qui démarrent avant qu'on ne commence à les écouter ? On pourrait essayer un contournement en utilisant <code>.complete</code>, mais ce n'est toujours pas infaillible, et que faire en cas d'images multiples ? Et, ummm, tout cela reste synchrone, et bloque donc le fil d'exécution principal.<br>
+ <br>
+ Alternativement, on pourrait faire notre propre promesse pour gérer ce genre de cas. (Voir l'exemple du <a href="https://github.com/mdn/promises-test">test de promesses</a> pour le code source, ou <a href="https://mdn.github.io/promises-test/">le voir fonctionner en direct</a>.)</p>
+
+<div class="note">
+<p><strong>Remarque </strong>: la mise en place d'un véritable service worker utiliserait la mise en cache et onfetch plutôt que l'API obsolète XMLHttpRequest. Ces fonctionnalités ne sont pas utilisées ici afin de se concentrer sur la compréhension des promesses.</p>
+</div>
+
+<pre class="brush: js notranslate">function imgLoad(url) {
+ return new Promise(function(resolve, reject) {
+ var request = new XMLHttpRequest();
+ request.open('GET', url);
+ request.responseType = 'blob';
+
+ request.onload = function() {
+ if (request.status == 200) {
+ resolve(request.response);
+ } else {
+ reject(Error('Image didn\'t load successfully; error code:' + request.statusText));
+ }
+ };
+
+ request.onerror = function() {
+ reject(Error('There was a network error.'));
+ };
+
+ request.send();
+ });
+}</pre>
+
+<p>On retourne une nouvelle promesse en utilisant le constructeur <code>Promise()</code>, qui prend en argument une fonction de rappel avec les paramètres <code>resolve</code> et <code>reject</code>. Quelque part dans la fonction, on a besoin de définir à quoi correspond pour la promesse d'être résolue avec succès ou bien d'être rejetée — dans ce cas, retourner un statut 200 OK status ou pas — et donc appleler <code>resolve</code> en cas de succès, ou <code>reject</code> en cas d'échec. Le reste du contenu de cette fonction correspond à une utilisation plutôt classique d'XHR, et n'appelle pas de commentaires particuliers pour le moment.</p>
+
+<p>Lorsqu'on appelle la fonction <code>imgLoad()</code>, on l'appelle avec l'url de l'image à charger, comme on pourrait s'en douter, mais le reste du code est un peu différent :</p>
+
+<pre class="brush: js notranslate">var body = document.querySelector('body');
+var myImage = new Image();
+
+imgLoad('myLittleVader.jpg').then(function(response) {
+ var imageURL = window.URL.createObjectURL(response);
+ myImage.src = imageURL;
+ body.appendChild(myImage);
+}, function(Error) {
+ console.log(Error);
+});</pre>
+
+<p>A la fin de l'appel de la fonction, on ajoute la méthode <code>then()</code> de la promesse, qui contient deux fonctions — la première est exécutée lorsque la promesse est résolue avec succès, et la seconde est appelée lorsque la promesse est rejetée. Dans le cas d'une résolution, on affiche l'image dans : <code>myImage</code> et on l'ajoute au <code>body</code> (son argument est la valeur <code>request.response</code> contenue dans la méthode <code>resolve</code> de la promesse); en cas de rejet, on retourne une erreur dans la console.</p>
+
+<p>Le tout se déroule de manière asynchrone.</p>
+
+<div class="note">
+<p><strong>Remarque </strong>: il est possible d'assembler des appels de promesse, par exemple:<br>
+ <code>myPromise().then(success, failure).then(success).catch(failure);</code></p>
+</div>
+
+<div class="note">
+<p><strong>Remarque </strong>: pour en savoir plus sur les promesses, consulter l'excellent article de Jake Archibald <a href="http://www.html5rocks.com/en/tutorials/es6/promises/">JavaScript Promises: there and back again</a>.</p>
+</div>
+
+<h2 id="Démo_de_service_workers">Démo de service workers</h2>
+
+<p>Pour illustrer quelques principes de base de l'enregistrement et de l'installation d'un service worker, voici une simple démo appelée <a href="https://github.com/mdn/sw-test">sw-test</a>, qui présente juste une galerie d'images Star wars Lego. Elle utilise une fonction pilotée par une promesse pour lire les données d'une image à partir d'un objet JSON et charger les images en utilisant Ajax, avant d'afficher les images en bas de page. Les choses restent statiques et simples pour le moment. Elle enregistre aussi, installe et active un service worker, et lorsque la specification est davantage supportée par les navigateurs, elle met en cache tous les fichiers requis pour un fonctionnement déconnecté !</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/8243/demo-screenshot.png" style="display: block; height: 410px; margin: 0px auto; width: 480px;"><br>
+ <br>
+ <br>
+ Vous pouvez consulter le <a href="https://github.com/mdn/sw-test/">code source sur GitHub</a>, et <a href="https://mdn.github.io/sw-test/">voir l'exemple en direct</a>. Le bout de code qui sera appelé est la promesse (voir <a href="https://github.com/mdn/sw-test/blob/gh-pages/app.js#L17-L42">app.js lines 17-42</a>), qui est une version modifiée du code présenté ci-dessus, dans la <a href="https://github.com/mdn/promises-test">démo du test de promesses</a>. Il en diffère de la façon suivante :</p>
+
+<ol>
+ <li>Dans l'original, on considère l'URL d'une image à charger. Dans cette version, on passe un fragment JSON contenant toutes les données d'une seule image (voir à quoi il ressemble dans <a href="https://github.com/mdn/sw-test/blob/gh-pages/image-list.js">image-list.js</a>). C'est parce que toutes les données pour que chaque promesse soit résolue doivent être passé avec la promesse, que c'est asynchrone. Si l'on passe juste l'url, et si l'on essaie alors d'accéder aux autres éléments dans le JSON séparément lorsqu'on itère plus tard avec la boucle <code>for()</code>, cela ne marchera pas, puisque la promesse ne se résolvera pas en même temps que les itérations sont faites (c'est un mécanisme synchrone.)</li>
+ <li>La promesse est résolue en réalité avec un tableau, puisqu'on veut rendre le blob de l'image chargée disponible à la fonction de résolution plus tard dans le code, mais aussi le nom de l'image, les crédits et le texte alternatif (voir <a href="https://github.com/mdn/sw-test/blob/gh-pages/app.js#L26-L29">app.js lines 26-29</a>). Les promesses se résolvent seulement avec un seul argument, aussi si l'on souhaite la résoudre avec des valeurs multiples, on a besoin d'utiliser un tableau ou un objet.</li>
+ <li>Pour accéder aux valeurs de la promesse résolue, on accède alors à cette fonction comme on peut s'y attendre (voir <a href="https://github.com/mdn/sw-test/blob/gh-pages/app.js#L55-L59">app.js lines 55-59</a>.) Cela peut sembler un peu étrange au premier abord, mais c'est la manière dont les promesses fonctionnent.</li>
+</ol>
+
+<h2 id="Introduction_aux_service_workers">Introduction aux service workers</h2>
+
+<p>Maintenant, c'est au tour des service workers !</p>
+
+<h3 id="Enregistrer_un_worker">Enregistrer un worker</h3>
+
+<p>Le premier bloc de code dans le fichier JavaScript de l'application — <code>app.js</code> — se présente comme suit. C'est le point d'entrée pour utiliser des service workers.</p>
+
+<pre class="brush: js notranslate">if ('serviceWorker' in navigator) {
+ navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/sw-test/' }).then(function(reg) {
+ // registration worked
+ console.log('Registration succeeded. Scope is ' + reg.scope);
+ }).catch(function(error) {
+ // registration failed
+ console.log('Registration failed with ' + error);
+ });
+};</pre>
+
+<ol>
+ <li>Le bloc extérieur effectue un test de détection de fonctionnalité pour s'assurer que les service workers sont supportés avant d'essayer d'en enregistrer un.</li>
+ <li>Ensuite, la fonction {{domxref("ServiceWorkerContainer.register()") }} est utilisée pour enregistrer le service worker de ce site, qui est juste un fichier JavaScript présent au sein de notre application (à noter qu'il s'agit de l'URL relative du fichier par rapport à l'origine, et non seulement le fichier JS qui le référence.)</li>
+ <li>Le paramètre <code>scope</code> est optionnel, et peut être utilisé pour spécifier le sous-ensemble du contenu qui doit être soumis au contrôle du service worker. Dans ce cas, on a spécifié '<code>/sw-test/'</code>, ce qui signifie tous les contenus présents sous l'origine de l'application. S'il n'est pas précisé, il correspondra de toute façon par défaut à cette valeur; il a été explicitement spécifié ici à titre d'illustration.</li>
+ <li>La fonction <code>.then()</code> de la promesse est utilisée pour chaîner un traitement en cas de succès à la structure de la promesse. Lorsque la promesse est résolue avec succès, le code qu'elle contient est exécuté.</li>
+ <li>Finalement, une fonction <code>.catch()</code> est chaînée à la fin, qui s'exécutera si la promesse est rejetée.</li>
+</ol>
+
+<p>A ce stade un service worker est enregistré, qui s'exécute dans le contexte d'un worker, et n'a donc aucun accès au DOM. Le code s'exécute ainsi dans le service worker, extérieurement aux pages normales dont il contrôle le chargement.<br>
+ <br>
+ Un seul service worker peut contrôler de nombreuses pages. Chaque fois qu'une page au sein du scope est chargée, le service worker est installé et opère sur la page. Attention, il faut faire un usage prudent des variables globales dans le script du service worker : chaque page ne dispose pas de son propre et unique worker.</p>
+
+<div class="note">
+<p><strong>Remarque </strong>: un service worker fonctionne comme un serveur proxy, permettant de modifier les requêtes et les réponses, de les remplacer par des éléments de son propre cache, et bien plus.</p>
+</div>
+
+<div class="note">
+<p><strong>Remarque </strong>: une chose importante à savoir au sujet des service workers est que si la détection de fonctionnalité est utilisée comme ci-dessus, les navigateurs qui ne supportent pas les service workers peuvent simplement utiliser l'application de la manière normalement attendue. De plus, si vous utilisez AppCache et SW sur une page, les navigateurs qui ne supportent pas SW mais supportent AppCache l'utiliseront, et les navigateurs qui supportent les deux ignoreront AppCache au profit de SW.</p>
+</div>
+
+<h4 id="Pourquoi_mon_service_worker_échoue_à_senregistrer">Pourquoi mon service worker échoue à s'enregistrer ?</h4>
+
+<p>Ce pourrait être pour les raisons suivantes :</p>
+
+<ol>
+ <li>L'application ne fonctionne pas au travers d'HTTPS</li>
+ <li>Le chemin du fichier du service worker file est syntaxiquement incorrect — il a besoin d'être exprimé relativement à l'origine, et non pas par rapport au répertoire racine. Dans l'exemple, le worker a comme emplacement <code>https://mdn.github.io/sw-test/sw.js</code>, et la racine de l'application est <code>https://mdn.github.io/sw-test/</code>. Mais la syntaxe du chemin s'écrit <code>/sw-test/sw.js</code>, <code>et non /sw.js</code>.</li>
+ <li>Le service worker considéré se trouve sur une origine différente de celle de l'application. Ce qui n'est pas permis.</li>
+</ol>
+
+<h3 id="Installer_et_activer_remplir_le_cache">Installer et activer : remplir le cache</h3>
+
+<p>Après l'enregistrement du service worker, le navigateur tente d'installer puis d'activer le service worker sur la page ou le site.<br>
+ <br>
+ L'événement install est déclenché lorsqu'une installation se termine avec succès. L'événement install est généralement utilisé pour remplir le cache local du navigateur avec les ressources nécessitées pour faire fonctionner l'application en mode déconnecté. A cet effet, la toute nouvelle API de stockage est utilisée — {{domxref("cache")}} — un espace global au niveau du service worker qui permet de stocker les ressources fournies par les réponses, et indexées par leurs requêtes. Cette API fonctionne d'une manière similaire au cache standard du navigateur, mais le cache demeure spécifique au domaine. Il persiste jusqu'à ce qu'il en soit décidé autrement — de nouveau, le contrôle reste total.</p>
+
+<div class="note">
+<p><strong>Remarque </strong>: L'API Cache n'est pas supportée par tous les navigateurs. (Voir la section {{anch("Compatibilité des navigateurs")}} pour plus d'informations.) Pour l'utiliser à l'heure actuelle, on peut envisager un polyfill comme celui fournit par la <a href="https://github.com/Polymer/topeka/blob/master/sw.js">démo Topeka de Google</a>, ou peut-être stocker les ressources dans <a href="/en-US/docs/Web/API/IndexedDB_API">IndexedDB</a>.</p>
+</div>
+
+<p>Commençons cette section par l'examen d'un exemple de code — c'est le <a href="https://github.com/mdn/sw-test/blob/gh-pages/sw.js#L1-L18">premier bloc présent dans le service worker</a>:</p>
+
+<pre class="brush: js notranslate">this.addEventListener('install', function(event) {
+  event.waitUntil(
+    caches.open('v1').then(function(cache) {
+      return cache.addAll([
+        '/sw-test/',
+        '/sw-test/index.html',
+        '/sw-test/style.css',
+        '/sw-test/app.js',
+        '/sw-test/image-list.js',
+        '/sw-test/star-wars-logo.jpg',
+        '/sw-test/gallery/',
+        '/sw-test/gallery/bountyHunters.jpg',
+        '/sw-test/gallery/myLittleVader.jpg',
+        '/sw-test/gallery/snowTroopers.jpg'
+      ]);
+    })
+  );
+});</pre>
+
+<ol>
+ <li>Un écouteur d'événement <code>install</code> est d'abord ajouté au service worker (d'où le  <code>this</code>), puis une méthode {{domxref("ExtendableEvent.waitUntil()") }} est chaînée à l'événement — cela garantit que le Service Worker ne s'installera pas tant que le code à l'intérieur de <code>waitUntil()</code> n'a pas été exécuté avec succès.</li>
+ <li>A l'intérieur de <code>waitUntil()</code> la méthode <a href="/en-US/docs/Web/API/CacheStorage/open"><code>caches.open()</code></a> est utilisée pour créer un nouveau cache appelé <code>v1</code>, ce qui constitue la version 1 du cache de ressources de notre site. Cette fonction retourne une promesse lorsque le cache est créé; une fois résolue, est appelée une fonction qui appelle elle-même <code>addAll()</code> sur le cache créé, avec pour paramètre un tableau d'URLs relatives à l'origine correspondant aux ressources à mettre en cache.</li>
+ <li>Si la promesse est rejetée, l'installation échoue, et le worker ne fait rien de plus. Le code peut être alors corrigé et l'opération retentée la prochaine fois que l'enregistrement survient.</li>
+ <li>Après une installation couronnée de succès, le service worker est activé. Cela ne fait pas une grande différence  la première fois que le service worker est installé/activé, mais cela fait plus sens lorsque le service worker est mis à jour (voir la section {{anch("Updating your service worker") }} plus bas.)</li>
+</ol>
+
+<div class="note">
+<p><strong>Remarque </strong>: <a href="/fr/docs/Web/API/Web_Storage_API">localStorage</a> fonctionne de la même façon que le cache du service worker, mais de manière synchrone, et il n'est donc pas autorisé dans les service workers.</p>
+</div>
+
+<div class="note">
+<p><strong>Remarque </strong>: <a href="/fr/docs/Web/API/API_IndexedDB">IndexedDB</a> peut être utilisé dans un service worker pour le stockage des donnés si nécessaire.</p>
+</div>
+
+<h3 id="Réponses_personnalisées_aux_requêtes">Réponses personnalisées aux requêtes</h3>
+
+<p>Une fois que les ressources du site sont mise en cache, les service workers doivent savoir quoi faire de ce contenu en cache. L'événement <code>fetch</code> permet de gérer cela facilement.</p>
+
+<p>Un événement <code>fetch</code> se déclenche à chaque fois qu'une ressource contrôlée par un service worker est retournée, ce qui inclut les documents à l'intérieur du contour spécifié, et toute ressource référencée dans ces documents (par exemple <code>si index.html</code> effectue une requête vers un autre domaine pour l'insertion d'une image, cela se fait encore au travers de son service worker.)</p>
+
+<p>On peut attacher un écouteur de l'événement <code>fetch</code> au service worker, puis appeler la méthode <code>respondWith()</code> sur l'événement pour détourner les réponses HTTP et les mettre à jour en leur jetant un sort particulier.</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+ event.respondWith(
+ // la magie opère ici
+ );
+});</pre>
+
+<p>On peut déjà simplement répondre avec la ressource en cache dont l'url correspond à celle de la requête réseau, dans chaque cas :</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+ event.respondWith(
+ caches.match(event.request)
+ );
+});</pre>
+
+<p><code>caches.match(event.request)</code> permet de mettre en correspondance chaque ressource demandée sur le réseau avec la ressource équivalente en cache, si elle se trouve être disponible. La comparaison est effectuée via l'url et diverses en-têtes, comme habituellement avec des requêtes HTTP normales.</p>
+
+<p>Voici quelques autres options disponibles pour que la magie opère (voir la <a href="/fr/docs/Web/API/Fetch_API">documentation de l'API Fetch </a>pour plus d'informations sur les objets {{domxref("Request")}} et {{domxref("Response")}}.)</p>
+
+<ol>
+ <li>
+ <p>Le constructeur <code>{{domxref("Response.Response","Response()")}}</code> permet de créer une réponse personnalisée. Dans cet exemple, une chaîne de caractères est simplement retournée :</p>
+
+ <pre class="brush: js notranslate">new Response('Hello from your friendly neighbourhood service worker!');</pre>
+ </li>
+ <li>
+ <p>La <code>Response</code> plus complexe ci-dessous montre qu'il est possible de passer optionnellement un ensemble d'en-têtes avec la réponse, émulant ainsi des en-têtes de réponse HTTP standards. Ici, on signale au navigateur quel est le type de contenu de notre réponse artificielle :</p>
+
+ <pre class="brush: js notranslate">new Response('&lt;p&gt;Hello from your friendly neighbourhood service worker!&lt;/p&gt;', {
+ headers: { 'Content-Type': 'text/html' }
+})</pre>
+ </li>
+ <li>
+ <p>Si une correspondance n'est pas trouvée en cache, on peut indiquer simplement au navigateur d'effectuer ({{domxref("GlobalFetch.fetch","fetch")}}) la requête réseau par défaut pour cette ressource, afin de récupérer cette nouvelle ressource sur le réseau si disponible :</p>
+
+ <pre class="brush: js notranslate">fetch(event.request)</pre>
+ </li>
+ <li>
+ <p>Si une correspondance n'est pas trouvée en cache et que le réseau n'est pas disponible, on peut alors faire correspondre la requête avec une page de rechange par défaut en guise de réponse en utilisant {{domxref("CacheStorage.match","match()")}}, comme suit :</p>
+
+ <pre class="brush: js notranslate">caches.match('/fallback.html');</pre>
+ </li>
+ <li>
+ <p>On peut récupérer beaucoup d'informations à propos de chaque requête en interrogeant les paramètres de l'objet {{domxref("Request")}} retourné par {{domxref("FetchEvent")}} :</p>
+
+ <pre class="brush: js notranslate">event.request.url
+event.request.method
+event.request.headers
+event.request.body</pre>
+ </li>
+</ol>
+
+<h2 id="Récupérer_des_requêtes_en_erreur">Récupérer des requêtes en erreur</h2>
+
+<p>On vient de voir que <code>caches.match(event.request)</code> est important lorsqu'il y a correspondance avec le cache du service worker, mais qu'en est-il des cas où rien ne correspond ? Si aucune sorte de gestionnaire d'erreur n'est fourni, la promesse est rejetée et une erreur réseau est retournée lorsqu'aucune correspondance n'est trouvée.</p>
+
+<p>Heureusement, la structure des service workers qui repose sur les promesses rend trivial la gestion des alternatives à une situation de succès. On pourrait faire ceci :</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+ event.respondWith(
+ caches.match(event.request).catch(function() {
+ return fetch(event.request);
+ })
+ );
+});</pre>
+
+<p>Si la promesse est rejetée, la fonction <code>catch()</code> retourne à la place la requête réseau par défaut, ce qui signifie que si le réseau est disponible la ressource sera chargée à partir du serveur.</p>
+
+<p>Plus malin encore, on pourrait non seulement récupérer la ressource à partir du serveur, mais aussi la sauvegarder dans le cache afin que les requêtes ultérieures pour cette ressource puissent être disponibles aussi en mode déconnecté. Cela signifierait que toute image supplémentaire ajoutée à la galerie Star Wars pourrait être récupérée par l'application et mise en cache. Le code suivant illustre ce mécanisme :</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+ event.respondWith(
+ caches.match(event.request).catch(function() {
+ return fetch(event.request).then(function(response) {
+ return caches.open('v1').then(function(cache) {
+ cache.put(event.request, response.clone());
+ return response;
+ });
+ });
+ })
+ );
+});</pre>
+
+<p>Ici on retourne la requête réseau par défaut au moyen de <code>return fetch(event.request)</code>, qui retourne lui-même une promesse. Lorsque cette promesse est résolue, on exécute une fonction qui sollicite le cache en utilisant <code>caches.open('v1')</code>; une promesse est de nouveau retournée. Lorsque cette promesse est résolue, <code>cache.put()</code> est utilisée pour ajouter la ressource au cache. La ressource est récupérée à partir de <code>event.request</code>, et la réponse est alors clonée avec <code>response.clone()</code> et ajoutée au cache. Le clone est placé dans le cache, et la réponse originale est retournée au navigateur et délivrée à la page qui la requiert.</p>
+
+<p>Pourquoi un clone ? Il se trouve que les flux de requête et de réponse peuvent seulement être lus une fois.  Afin de retourner la réponse au navigateur et de la mettre en cache, elle doit être clonée. Aussi, l'original est retourné au navigateur tandis que le clone est envoyé dans le cache. Ils sont chacun lus une seule fois.</p>
+
+<p>Le dernier problème qui demeure alors est l'échec de la requête au cas où elle n'a aucune correspondance dans le cache et que le réseau n'est pas disponible. Fournir un document de rechange par défaut permet quoiqu'il arrive, à l'utilisateur de récupérer quelque chose :</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+ event.respondWith(
+ caches.match(event.request).catch(function() {
+ return fetch(event.request).then(function(response) {
+ return caches.open('v1').then(function(cache) {
+ cache.put(event.request, response.clone());
+ return response;
+ });
+ });
+ }).catch(function() {
+    return caches.match('/sw-test/gallery/myLittleVader.jpg');
+  })
+ );
+});</pre>
+
+<p>Une image de rechange a été choisie parce que les seules mises à jour susceptibles d'échouer sont les nouvelles images, puisque tous les autres éléments dépendent de l'installation comme vu précédemment dans la description de l'écouteur de l'événement <code>install</code>.</p>
+
+<h2 id="Suggestion_damélioration_dun_modèle_de_code">Suggestion d'amélioration d'un modèle de code</h2>
+
+<p>Ce code utilise un chaînage de promesses plus standard et retourne la réponse au document sans avoir à attendre que <code>caches.open()</code> soit résolue :</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+  var response;
+  event.respondWith(caches.match(event.request).catch(function() {
+    return fetch(event.request);
+  }).then(function(r) {
+    response = r;
+    caches.open('v1').then(function(cache) {
+      cache.put(event.request, response);
+    });
+    return response.clone();
+  }).catch(function() {
+    return caches.match('/sw-test/gallery/myLittleVader.jpg');
+  }));
+});</pre>
+
+<h2 id="Mettre_à_jour_le_service_worker"><a id="Updating your service worker" name="Updating your service worker">Mettre à jour le service worker</a></h2>
+
+<p>Si le service worker a été précédemment installé, et qu'une nouvelle version du worker est disponible au chargement ou au rafraîchissement de la page, la nouvelle version est installée en arrière-plan, mais pas encore activée. Elle ne sera activé que lorsqu'il n'y aura plus aucune page chargée qui utilise encore l'ancien service worker. Dès lors qu'il n'y a plus de telles pages encore chargées, le nouveau service worker est activé.</p>
+
+<p>On souhaite mettre à jour l'écouteur d'événement <code>install</code> dans le nouveau service worker de la façon suivante (à noter le nouveau numéro de version) :</p>
+
+<pre class="brush: js notranslate">this.addEventListener('install', function(event) {
+ event.waitUntil(
+ caches.open('v2').then(function(cache) {
+ return cache.addAll([
+ '/sw-test/',
+ '/sw-test/index.html',
+ '/sw-test/style.css',
+ '/sw-test/app.js',
+ '/sw-test/image-list.js',
+
+ …
+
+ // include other new resources for the new version...
+ ]);
+ });
+ );
+});</pre>
+
+<p>Tandis que la mise à jour se produit, la version précédente est encore en charge de récupérer des ressources. La nouvelle version est installée en arrière-plan. Le nouveau cache se nomme v2, et ainsi ne perturbe en rien le précédent cache nommé v1.</p>
+
+<p>Lorsque plus aucune page n'utilise la version actuelle, le nouveau worker est activé et prend en charge les requêtes.</p>
+
+<h3 id="Supprimer_les_anciens_caches">Supprimer les anciens caches</h3>
+
+<p>Il existe un événement <code>activate</code>. Il est généralement utilisé pour faire un travail qui aurait interrompu le fonctionnement d'une version précédente alors qu'elle était encore en cours d'utilisation, comme par exemple se débarrasser des anciens caches. Il est aussi utile pour supprimer des données qui ne sont plus nécessaires afin d'éviter de surcharger l'espace disque — chaque navigateur dispose d'une limite physique quant à la capacité de stockage en cache dont le service worker peut bénéficier. Le navigateur gère au mieux l'espace disque, mais il peut supprimer le stockage du Cache pour une origine. Le navigateur supprimera généralement toutes les données d'une origine ou bien aucune.</p>
+
+<p>Les promesses passées à <code>waitUntil()</code> bloqueront les autres événements jusqu'à réalisation complète, ainsi on a l'assurance que l'opération de nettoyage aura été menée à terme au moment où surviendra le premier événement <code>fetch</code> du nouveau cache.</p>
+
+<pre class="brush: js notranslate">this.addEventListener('activate', function(event) {
+ var cacheWhitelist = ['v2'];
+
+ event.waitUntil(
+ caches.keys().then(function(keyList) {
+ return Promise.all(keyList.map(function(key) {
+ if (cacheWhitelist.indexOf(key) === -1) {
+ return caches.delete(key);
+ }
+ }));
+ })
+ );
+});</pre>
+
+<h2 id="Outils_de_développement">Outils de développement</h2>
+
+<p>Chrome dispose de <code>chrome://inspect/#service-workers</code>, qui montre l'activité du service worker courant et le stockage sur l'appareil, et <code>chrome://serviceworker-internals</code>, qui offre plus de détails et permet de démarrer/arrêter/déboguer le processus du worker. A l'avenir, des modes dégradé/déconnecté seront ajoutés pour simuler des connexions mauvaises ou inexistantes, ce qui sera une bonne chose.</p>
+
+<p>Firefox a aussi commencé à implanter quelques outils utiles concernant les service workers :</p>
+
+<ul>
+ <li>Consulter <a>about:serviceworkers</a> pour voir quels SWs sont enregistrés et les mettre à jour ou les supprimer.</li>
+ <li>Lors de tests, il est possible de contourner la restriction HTTPS en cochant l'option "Activer les Service Workers via HTTP (lorsque la boîte à outils est ouverte)" dans les options des outils de développement de Firefox (la roue dentée dans le menu.)</li>
+</ul>
+
+<h2 id="Spécifications">Spécifications</h2>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">Spécification</th>
+ <th scope="col">Statut</th>
+ <th scope="col">Commentaire</th>
+ </tr>
+ <tr>
+ <td>{{SpecName('Service Workers', '')}}</td>
+ <td>{{Spec2('Service Workers')}}</td>
+ <td>Définition initiale .</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Compatibilité_des_navigateurs">Compatibilité des navigateurs</h2>
+
+<div>{{CompatibilityTable}}</div>
+
+<div id="compat-desktop">
+<table class="compat-table">
+ <tbody>
+ <tr>
+ <th>Fonctionnalité</th>
+ <th>Chrome</th>
+ <th>Firefox (Gecko)</th>
+ <th>Internet Explorer</th>
+ <th>Opera</th>
+ <th>Safari (WebKit)</th>
+ </tr>
+ <tr>
+ <td>Basic support</td>
+ <td>{{CompatChrome(40.0)}}</td>
+ <td>{{ CompatGeckoDesktop("33.0") }}</td>
+ <td>{{CompatNo}}</td>
+ <td>24</td>
+ <td>{{CompatNo}}</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+<div id="compat-mobile">
+<table class="compat-table">
+ <tbody>
+ <tr>
+ <th>Fonctionnalité</th>
+ <th>Android</th>
+ <th>Chrome for Android</th>
+ <th>Firefox Mobile (Gecko)</th>
+ <th>Firefox OS</th>
+ <th>IE Phone</th>
+ <th>Opera Mobile</th>
+ <th>Safari Mobile</th>
+ </tr>
+ <tr>
+ <td>Basic support</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatChrome(40.0)}}</td>
+ <td>{{ CompatVersionUnknown }}</td>
+ <td>{{ CompatVersionUnknown }}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{ CompatVersionUnknown() }}</td>
+ <td>{{CompatNo}}</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+<h2 id="Voir_aussi">Voir aussi</h2>
+
+<ul>
+ <li><a href="https://jakearchibald.github.io/isserviceworkerready/">Is ServiceWorker ready?</a></li>
+ <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a></li>
+ <li><a href="/en-US/docs/Web/Guide/Performance/Using_web_workers">Using web workers</a></li>
+</ul>