Les RENCONTRES INTERACTIVES de Caen #14

EMBAUCHEr

UN SERVICE WORKER

@alexisjanvier

@marmelab

Alexis Janvier

developppeur chez marmelab

depuis 2014

Atelier d'innovation digitale, développe vos projets d'innovation web et mobile avec agilité, pragmatisme et gourmandise.

à Nancy, Ils n'y connaissent rien à l'équitation.

Avant d'aborder les services workerS, voyons Comment fonctionne UNE APPLICATION WEB

Le navigateur demande une page html à un serveur

Une application web demande des données à une API

Plus globalement, le navigateur va demander

  • un type de document (une page html, une image, un fichier css, un json, ...)
  • à un serveur web
  • sur une url particulière
  • via le protocole http

Le serveur va répondre en renvoyant

  • le document s'il existe ou que le serveur peut le générer (statut 200)
  • un code d'erreur si le document n'existe pas (400) ou que le serveur échoue lors de la génération du document (500) ou encore que le serveur n'est pas disponible (503).

On présente souvent un Service worker comme un Proxy entre le navigateur et le serveur web

C'est à dire ?

En vrai ce n'est pas un chat,

mais un fichier javascript

APPELÉ par la page html,

exécuté par le navigateur INDÉPENDAMMENT de la page elle-même.


<script type="text/javascript">
    if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('service-worker.js', { scope: '/' })
        .then(function(reg) {
            mainMessage('notify', 'Service worker is started');
        }).catch(function(error) {
            mainMessage('alert', 'Registration failed with ' + error);
        });
    } else {
        mainMessage('alert', 'Your browser do not support Service Worker');
    }
</script>

page.html :

const CACHE_NAME = 'sw-demo_1';
const urlsToCache = ['/index.html'];

self.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open(CACHE_NAME)
        .then(cache => cache.addAll(urlsToCache))
        .then(() => self.skipWaiting())
    );
});


self.addEventListener('activate', (event) => {
    event.waitUntil(
        caches.keys()
            .then(keys => {
                return Promise.all(keys
                    .filter(key => key !== CACHE_NAME)
                    .map(key => caches.delete(key))
                );
            })
            .then(() => self.clients.claim())
    );
});

self.addEventListener('fetch', function(event) {
    event.respondWith(
        fetch(event.request)
            .catch(() => caches.match(event.request))
    );
});

service-worker.js :

LeS points marquantS

navigator.serviceWorker.register('service-worker.js', { scope: '/' })

1 - Le service worker est lancé dans un processus indépendant de celui de la page web

2 - Tout le code du service worker est asynchrone

return Promise.all(keys [...]);

3 - Le service worker a un cycle de vie : install -> activate -> fetch

4 - Le service worker a accès à un mécanisme de cache

caches.open(CACHE_NAME)

5 - Le service worker ne marche qu'en https

6 - Un dernier point ... que nous verrons plus tard

Mettre un site offline

Tout d'abord, lorsqu'un service worker est démarré, il commence sa phase d'installation. Lors de cette phase, le développeur va pouvoir indiquer un certain nombre d'éléments à sauvegarder dans le cache, par exemple :

Le cache est une simple "base de donnée" clé/valeur : la clé est l'url, la valeur est ce qui est retourné par le serveur (du html, du css, une image ...).

const urlsToCache = [
    '/index.html',
    '/playlist.html',
    '/css/sw-demo.css',
    '/images/catWorker.jpg',
    '/covers/xeniaRubinos.jpg',
    '/js/sw-demo.js',
];

Une fois le service worker installé et activé, il va pouvoir écouter toutes les requêtes effectuées par le navigateur vers le serveur.

La stratégie la plus simple pour permettre à un site de s'afficher hors-ligne va consister à :

1 - Demander au service worker de mettre l'intégralité du site en cache lors de l'installation

2 - Ne rien faire si la requête envoyée au serveur est retournée sans erreur.

3 - En cas de retour en erreur du serveur (ou de non réponse), demander au service worker de retourner la valeur en cache correspondant à cette requête.

DEMO TIME !

https://sw.alexisjanvier.space
Code de la démo : https://github.com/marmelab/service-worker-demo

Cette capacité à rendre un site hors ligne est déjà très séduisante.

 

Mais cela n'apporte en fait pas grand chose de plus que feue l' application Cache (AppCache) et son fichier manifest (*.appcache)

La très grande force des services workers est de permettre l'implémentation de n'importe quelle stratégie de cache

- Mise à jour de cache

- Ne servir que la home en mode offline + une page générique

- Appeler des images différentes selon que l'on est sur mobile ou desktop

- Strategie de Cache First

- Analyser la page retournée pour identifier les liens et les mettre en cache

- ...

Gleb Bahmutov a même codé intégralement une application "express" dans un service worker

https://github.com/bahmutov/todomvc-express-and-service-worker

Et ce n'est pas tout !

 

- Push API pour faire des notifications comme sur les mobiles

- Web Background Synchronization pour faire de l'édition hors ligne

Alors pourquoi

tout le monde

n'utilise pas

les services workers ?

<script type="text/javascript">
    if ('serviceWorker' in navigator) { ...

Et oui, les services workers ne sont pas disponibles sur tous les navigateurs ...

Concernant IE, cela n'est pas forcément très étonnant ...

Par contre, c'est plus surprenant de la part de Safari

Peut-être à cause des progressive web apps ?

Qu'est ce qu'une Progressive web app ?

Une Progressive Web App utilise les possibilités du web moderne pour délivrer une expérience utilisateur similaire à une application native. – Progressive Web Apps

  1. Responsive: elle doit s'adapter à plusieurs types d'écran (html, css)
  2. Connectivity independent: elle doit fonctionner hors ligne (sw)
  3. App-like-interactions: elle doit avoir une interface identique aux applications (sw, App Shell, UX, ...)
  4. Fresh: elle doit se mettre à jour de manière transparente (sw)
  5. Safe: elle doit être sécurisée via le https
  6. Discoverable: identifiable comme une application (W3C Manifests)
  7. Re-engageable: elle doit permettre les notifications (sw)
  8. Installable: elle doit être installable (W3C Manifests)
  9. Linkable: elle doit être très facilement partageable

Frances Berriman et Alex Russell définissent 9 caractéristiques pour une progressive web app

Avec tous ces points, dont les technos sont disponibles, on peut donc faire des applications pouvant se passer des stores pour être distribuées.
 

Conclusion

Le service worker est vraiment un outil très puissant et très flexible.
Mais son absence de support sur IE et Safari est un vrai problème.
 

Donc si :
 - vous avez les conditions permettant d'imposer les navigateurs,
 - un budget suffisant pour investir sur une partie seulement de vos utilisateurs,
 - une volonté d'être avant-gardiste,
 

FONCEZ !

Sinon, cela reste pour le moment difficile à vendre à un client.

MERCI

Et si vous avez trouvé qu'il n'y avait pas

assez de code dans cette présentation

Rendez-vous mardi 28 Mars

pour l'édition #28 des CaenCamp

www.meetup.com/CaenCamp

@caencamp