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. Partir sans rien serait donc un gaspillage. Vous continuez donc à 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 seulement vous aviez attendu.

Les service workers résolvent la partie chargement de la page 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 n'est pas connecté, nous lui disons "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 le voir en action, 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 l'opération échoue, une nouvelle tentative de 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 à l'aide de la même balise qu'une synchronisation en attente, elle se combine à 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 cinq événements de synchronisation distincts, utilisez simplement des balises 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, importations 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.

Une autre démonstration !

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

Essayez-le 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. 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é.

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 parce que Safari et Edge ne sont pas encore compatibles avec les services 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 de 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 pendant 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 périodique en arrière-plan". 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.

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