Présentation de la synchronisation en arrière-plan

Jake Archibald
Jake Archibald

Publié le 8 décembre 2015

La synchronisation en arrière-plan est une API Web qui vous permet de différer des actions jusqu'à ce que l'utilisateur dispose d'une connectivité stable. Cela vous permet d'aider les utilisateurs à envoyer les fichiers de leur choix dès que possible.

Browser Support

  • Chrome: 89.
  • Edge: 89.
  • Firefox: not supported.
  • Safari: not supported.

Source

Problème

Internet est un excellent moyen de perdre du temps. Sans perdre de temps sur le Internet, nous ne saurions pas que les chats n'aiment pas les fleurs, les caméléons adorent les bulles, ou qu' Eric Bidelman est un héros du mini-golf de la fin des années 90.

Mais parfois, nous ne cherchons pas à perdre du temps. L'expérience utilisateur idéale ressemble plutôt à ceci :

  1. Le téléphone est sorti de la poche.
  2. L'utilisateur atteint un objectif mineur.
  3. Le téléphone est remis dans la poche.
  4. L'utilisateur reprend sa vie.

Malheureusement, cette expérience est souvent interrompue par une mauvaise connectivité. Cela nous est tous arrivé. Vous regardez un écran blanc ou un indicateur de chargement, et vous savez que vous devriez simplement abandonner et continuer votre vie, mais vous attendez encore 10 secondes au cas où. Après ces 10 secondes ? Rien.

Mais pourquoi abandonner maintenant ? Vous avez déjà investi du temps, alors partir sans rien serait un gaspillage. Vous continuez donc à attendre. À ce stade, vous voulez abandonner, mais vous savez que la seconde où vous le ferez sera celle où tout se serait chargé si vous aviez attendu.

Les service workers résolvent le problème du chargement des pages en vous permettant de diffuser du contenu à partir d'un cache. Mais que se passe-t-il lorsque la page doit envoyer quelque chose au serveur ?

Pour le moment, si l'utilisateur appuie sur "Envoyer" dans un message, il doit regarder un indicateur de chargement jusqu'à ce qu'il se termine. S'il tente de quitter la page ou de fermer l'onglet, nous utilisons onbeforeunload pour afficher un message tel que "Non, je dois vous demander de regarder encore un peu cet indicateur de chargement. Désolé". Si l'utilisateur n'a pas de connexion, nous lui indiquons : "Désolé, vous devez revenir plus tard et réessayer".

La synchronisation en arrière-plan vous permet de faire mieux.

La solution

La vidéo suivante présente Emojoy, une démo de chat uniquement avec des emojis. Il s'agit d'une progressive web app qui fonctionne hors connexion. L'application utilise des messages push et des notifications, ainsi que la synchronisation en arrière-plan.

Si l'utilisateur tente d'envoyer un message alors qu'il n'a aucune connectivité, le message est envoyé en arrière-plan une fois qu'il est connecté.

La possibilité d'envoyer des messages en arrière-plan de cette manière améliore également les performances perçues. L'application n'a pas besoin de se soucier de l'envoi du message. Elle peut donc l'ajouter immédiatement à la sortie.

La synchronisation en arrière-plan est disponible à partir de Chrome 49.

Demander une synchronisation en arrière-plan

Dans le style Web extensible, il s'agit d'une fonctionnalité de bas niveau qui vous permet de faire ce dont vous avez besoin. Vous demandez qu'un événement soit déclenché lorsque l'utilisateur est connecté, ce qui est immédiat s'il l'est déjà. Ensuite, vous écoutez cet événement et faites ce que vous devez faire.

Comme les messages push, il utilise un service worker comme cible d'événement, ce qui lui permet de fonctionner lorsque la page n'est pas ouverte. Pour commencer, enregistrez une synchronisation à partir d'une page :

// Register your service worker:
navigator.serviceWorker.register('/sw.js');

// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
  return swRegistration.sync.register('myFirstSync');
});
 ```

Then listen for the event in `/sw.js`:

```js
self.addEventListener('sync', function(event) {
  if (event.tag == 'myFirstSync') {
    event.waitUntil(doSomeStuff());
  }
});

Voilà, c'est terminé ! doSomeStuff() doit renvoyer une promesse indiquant la réussite ou l'échec de ce qu'il tente de faire. Si elle est remplie, la synchronisation est terminée. En cas d'échec, une autre synchronisation est planifiée pour réessayer. Les synchronisations de nouvelle tentative attendent également la connectivité et utilisent un intervalle exponentiel entre les tentatives.

Le nom de tag de la synchronisation ("myFirstSync" dans l'exemple) doit être unique pour une synchronisation donnée. Si vous enregistrez une synchronisation à l'aide du même tag qu'une synchronisation en attente, elle fusionne avec la synchronisation existante. Cela signifie que vous pouvez vous inscrire à une synchronisation "clear-outbox" chaque fois que l'utilisateur envoie un message, mais s'il envoie cinq messages hors connexion, vous n'obtiendrez qu'une seule synchronisation lorsqu'il sera en ligne. Pour obtenir cinq événements de synchronisation distincts, utilisez des tags uniques.

Voici une démo qui utilise l'événement de synchronisation pour afficher une notification.

Utilisations de la synchronisation en arrière-plan

Idéalement, vous l'utiliserez pour planifier l'envoi de données qui vous intéressent au-delà de la durée de vie de la page. Messages de chat, e-mails, mises à jour de documents, modifications de paramètres, importations de photos ou tout contenu que vous souhaitez atteindre le serveur, même si l'utilisateur quitte la page ou ferme l'onglet. La page peut les stocker dans un magasin "outbox" dans indexedDB, et le service worker les récupère et les envoie.

Vous pouvez également l'utiliser pour récupérer de petits éléments de données.

Démo Wikipédia hors connexion

Il s'agit de la démo Wikipédia hors connexion que j'ai créée pour Supercharging Page Load. Depuis, j'y ai ajouté de la magie de synchronisation en arrière-plan.

Essayez vous-même :

  1. Laissez votre navigateur ouvert sur cet onglet.
  2. Passez hors connexion en activant le mode Avion ou en désactivant le Wi-Fi.
  3. Cliquez sur un lien vers un autre article.
  4. Vous devriez être informé que la page n'a pas pu être chargée (cela s'affiche également si le chargement de la page prend un certain temps).
  5. Acceptez les notifications.
  6. Fermez le navigateur.
  7. Se connecter
  8. Vous recevez une notification lorsque l'article est téléchargé, mis en cache et prêt à être consulté.

Grâce à ce modèle, l'utilisateur peut mettre son téléphone dans sa poche et continuer sa vie, sachant que le téléphone l'avertira lorsqu'il aura récupéré ce qu'il voulait.

Autorisations

Les démos que j'ai présentées utilisent des notifications Web, qui nécessitent une autorisation, mais la synchronisation en arrière-plan elle-même n'en nécessite pas.

Les événements de synchronisation se terminent souvent lorsque l'utilisateur a une page ouverte sur le site. Par conséquent, demander l'autorisation de l'utilisateur serait une mauvaise expérience. Au lieu de cela, nous limitons le moment où les synchronisations peuvent être enregistrées et déclenchées pour éviter les abus. Exemple :

  • Vous ne pouvez vous inscrire à un événement de synchronisation que lorsque l'utilisateur a une fenêtre ouverte sur le site.
  • La durée d'exécution de l'événement est limitée. Vous ne pouvez donc pas l'utiliser pour envoyer un ping à un serveur toutes les x secondes, extraire des bitcoins, etc.

Bien sûr, ces restrictions peuvent être assouplies ou renforcées en fonction de l'utilisation réelle.

Amélioration progressive

En attendant que la synchronisation en arrière-plan devienne une référence, vous pouvez l'utiliser comme une amélioration progressive :

if ('serviceWorker' in navigator && 'SyncManager' in window) {
  navigator.serviceWorker.ready.then(function(reg) {
    return reg.sync.register('tag-name');
  }).catch(function() {
    // system was unable to register for a sync,
    // this could be an OS-level restriction
    postDataFromThePage();
  });
} else {
  // serviceworker/sync not supported
  postDataFromThePage();
}

Si les service workers ou la synchronisation en arrière-plan ne sont pas disponibles, il vous suffit de publier le contenu de la page comme vous le feriez aujourd'hui.

Il est intéressant d'utiliser la synchronisation en arrière-plan, même si l'utilisateur semble avoir une bonne connectivité, car elle vous protège contre les navigations et les fermetures d'onglets lors de l'envoi de données.

L'avenir

Nous prévoyons de déployer la synchronisation en arrière-plan dans une version stable de Chrome au premier semestre 2016, tout en travaillant sur une variante, la "synchronisation en arrière-plan périodique". Avec la synchronisation en arrière-plan périodique, vous pouvez demander un événement limité par un intervalle de temps, l'état de la batterie et l'état du réseau. Cela nécessitera bien sûr l'autorisation de l'utilisateur, et il appartiendra également au navigateur de déterminer quand et à quelle fréquence ces événements seront déclenchés. En d'autres termes, un site d'actualités peut demander à se synchroniser toutes les heures, mais le navigateur peut savoir que vous ne consultez ce site qu'à 7h00. La synchronisation sera donc déclenchée tous les jours à 6h50. Cette idée est un peu plus éloignée que la synchronisation ponctuelle, mais elle arrive.

Petit à petit, nous transposons les modèles réussis d'Android et d'iOS sur le Web, tout en conservant ce qui fait la grandeur du Web.