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

Jake Archibald
Jake Archibald

La synchronisation en arrière-plan est une nouvelle API Web qui vous permet de différer les actions jusqu'à ce que l'utilisateur dispose d'une connectivité stable. Cela garantit que tout ce que l'utilisateur souhaite envoyer est effectivement envoyé.

Problème

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

Mais parfois, juste parfois, nous ne voulons pas perdre de temps. L'expérience utilisateur souhaitée est plutôt la suivante:

  1. Téléphone sorti de la poche.
  2. Atteignez un objectif mineur.
  3. Téléphone remis dans la poche.
  4. Reprendre la vie.

Malheureusement, cette expérience est souvent interrompue par une mauvaise connectivité. Cela nous est tous arrivé. Vous regardez un écran blanc ou un voyant en rotation, et vous savez que vous devriez simplement abandonner et passer à autre chose, 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, donc partir avec rien serait une perte, alors vous continuez à attendre. À ce stade, vous avez envie d'abandonner, mais vous savez que la seconde où vous le ferez, c'est la seconde avant que tout ne se charge si vous aviez seulement attendu.

Les service workers résolvent le problème de 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 ?

Actuellement, si l'utilisateur clique sur "Envoyer" pour un message, il doit attendre que la roue de chargement s'arrête. 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 cette icône de chargement. Désolé". Si l'utilisateur ne dispose d'aucune connexion, nous lui indiquons "Désolé, vous devez revenir plus tard et réessayer".

C'est n'importe quoi. La synchronisation en arrière-plan vous permet de faire mieux.

Solution

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

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

Depuis mars 2016, la synchronisation en arrière-plan est disponible dans Chrome à partir de la version 49. Pour ce faire, procédez comme suit:

  1. Ouvrez Emojoy.
  2. Passez en mode hors connexion (en activant le mode Avion ou en vous rendant dans une cage de Faraday locale).
  3. Saisissez un message.
  4. Revenez à l'écran d'accueil (vous pouvez également fermer l'onglet ou le navigateur).
  5. Connectez-vous à Internet.
  6. Le message est envoyé en arrière-plan.

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

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 dispose d'une connectivité, ce qui est immédiat s'il en dispose déjà. Vous écoutez ensuite cet événement et effectuez les actions nécessaires.

Comme la messagerie 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());
  }
});

Et voilà ! Dans l'exemple ci-dessus, doSomeStuff() doit renvoyer une promesse indiquant le succès ou l'échec de l'opération qu'il tente d'effectuer. Si la promesse est remplie, la synchronisation est terminée. Si elle échoue, une nouvelle synchronisation sera planifiée. Les tentatives de synchronisation attendent également la connectivité et utilisent un intervalle exponentiel entre les tentatives.

Le nom de la balise de la synchronisation ('myFirstSync' dans l'exemple ci-dessus) doit être unique pour une synchronisation donnée. Si vous vous inscrivez à une synchronisation avec le même tag que celui d'une synchronisation en attente, celle-ci fusionne avec la synchronisation existante. Cela signifie que vous pouvez vous inscrire pour une synchronisation de la boîte de réception chaque fois que l'utilisateur envoie un message. Toutefois, s'il envoie cinq messages en mode hors connexion, vous ne recevrez qu'une seule synchronisation lorsqu'il sera en ligne. Si vous souhaitez créer cinq événements de synchronisation distincts, utilisez simplement des tags uniques.

Voici une démonstration simple qui ne fait que le strict minimum. Elle utilise l'événement de synchronisation pour afficher une notification.

À quoi puis-je utiliser 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, importation de photos, etc. : tout ce que vous souhaitez transmettre au serveur, même si l'utilisateur quitte la page ou ferme l'onglet. La page peut les stocker dans un magasin "boîte de sortie" dans indexedDB, et le service worker les récupérera et les enverra.

Vous pouvez toutefois l'utiliser pour extraire de petits éléments de données.

Encore une démonstration !

Voici la démonstration de Wikipédia hors connexion que j'ai créée pour Booster le chargement des pages. J'y ai ensuite ajouté un peu de magie pour la synchronisation en arrière-plan.

Essayez par vous-même. Assurez-vous d'utiliser Chrome 49 ou une version ultérieure, puis:

  1. Accédez à un article, par exemple Chrome.
  2. Passez en mode hors connexion (en activant le mode Avion ou en souscrivant un abonnement mobile de mauvaise qualité comme moi).
  3. Cliquez sur un lien vers un autre article.
  4. Un message vous indiquera que la page n'a pas pu être chargée (ce message s'affiche également si la page met un certain temps à se charger).
  5. Accepter 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é.

Avec ce modèle, l'utilisateur peut mettre son téléphone dans sa poche et vaquer à ses occupations, sachant qu'il sera alerté lorsqu'il aura obtenu ce qu'il voulait.

Autorisations

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

Les événements de synchronisation se terminent souvent lorsque l'utilisateur a une page ouverte sur le site. Demander l'autorisation de l'utilisateur serait donc une mauvaise expérience. Nous limitons plutôt les moments où les synchronisations peuvent être enregistrées et déclenchées pour éviter tout abus. Exemple :

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

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

Amélioration progressive

Il faudra un certain temps avant que tous les navigateurs soient compatibles avec la synchronisation en arrière-plan, en particulier étant donné que Safari et Edge ne sont pas encore compatibles avec les service workers. L'amélioration progressive est utile dans ce cas:

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, publiez simplement le contenu depuis la page, comme vous le feriez aujourd'hui.

Il est utile d'utiliser la synchronisation en arrière-plan, même si l'utilisateur semble disposer d'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 lancer 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 le navigateur déterminera également quand et à quelle fréquence ces événements se déclencheront. 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'à 7h. La synchronisation se déclenchera donc tous les jours à 6h50. Cette idée est un peu plus éloignée que la synchronisation ponctuelle, mais elle arrivera.

Progressivement, nous transposons sur le Web les modèles Android et iOS qui ont fait leurs preuves, tout en conservant ce qui fait la qualité du Web.