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

Jake Archibald
Jake Archibald

Synchronisation en arrière-plan est une nouvelle API Web qui vous permet de reporter les actions jusqu'à ce que l'utilisateur dispose la connectivité. Cela garantit que tout ce que l'utilisateur souhaite envoyer est réellement envoyé.

Problème

Internet est idéal pour perdre du temps. Sans perdre de temps sur Internet, nous ignorons que les chats n'aiment pas les fleurs, les caméléons adorent les bulles ou que notre propre Eric Bidelman est un héros du putt putt de la fin des années 1990.

Mais parfois, mais parfois, nous ne cherchons pas à perdre du temps. L'utilisateur souhaité l'expérience utilisateur ressemble davantage à:

  1. Un téléphone hors de votre poche
  2. Atteindre un objectif mineur.
  3. Le téléphone est de retour dans la poche.
  4. Reprendre la vie.

Malheureusement, cette expérience est souvent interrompue par une mauvaise connectivité. Nous sommes tous passés par là. Vous regardez un écran blanc ou une icône de chargement, et vous savez que vous devriez abandonner et continuer votre vie, mais vous lui accordez encore 10 secondes au cas où. Au bout de 10 secondes ? Rien.

Mais pourquoi abandonner maintenant ? Vous avez déjà investi du temps, donc partir avec rien serait une perte, et vous continuez à attendre. À ce stade, vous voulez abandonner, mais vous savez que la seconde où vous le faites est la seconde avant que tout ne soit chargé si seulement vous aviez 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", sur un message, il doit regarder une icône de chargement jusqu'à ce qu'il se termine. S'ils tentent de quitter la page ou de fermer l'onglet, nous utilisons onbeforeunload pour afficher un message du type "Non, je dois que vous regardiez 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 nul. La synchronisation en arrière-plan vous permet de faire mieux.

Solution

La vidéo suivante présente Emojoy, une démonstration de chat réservée aux emoji. Il s'agit d'une application Web progressive qui fonctionne en priorité hors connexion. L'application utilise les messages et les notifications push, et la synchronisation en arrière-plan.

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

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. Déconnectez-vous (en mode Avion ou rendez-vous dans la cage Faraday la plus proche).
  3. Saisissez un message.
  4. Revenez à l'écran d'accueil (fermez l'onglet ou le navigateur si vous le souhaitez).
  5. Connectez-vous.
  6. Le message est envoyé en arrière-plan !

Ce type d'envoi en arrière-plan entraîne également une amélioration des performances perçue. Comme l'application n'a pas besoin d'accorder une telle importance à l'envoi du message, elle peut immédiatement ajouter le message à la sortie.

Demander une synchronisation en arrière-plan

Dans le style Web étendu, il s'agit d'un fonctionnalité de bas niveau qui vous donne la liberté de faire ce dont vous avez besoin. Vous demandez un l'événement doit être déclenché lorsque l'utilisateur dispose d'une connectivité, lequel est immédiat si l'utilisateur dispose déjà d'une connectivité. Ensuite, vous écoutez cet événement et faites ce que vous ce que vous devez faire.

Tout comme les messages push, elles utilisent un service worker comme cible d'événement, ce qui lui permet de fonctionner lorsque la page n'est pas ouverte. Pour commencer, demandez 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 ce qui précède, doSomeStuff() doit renvoyer une promesse indiquant la réussite ou l'échec de la tâche en cours. Si c'est le cas, la synchronisation est terminée. En cas d'échec, une nouvelle tentative de synchronisation est programmée. Les nouvelles tentatives de synchronisation attendent également la connectivité et appliquent un intervalle exponentiel entre les tentatives.

Le nom du tag de 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 demander à bénéficier d'une "boîte d'envoi" effectuer la synchronisation chaque fois que l'utilisateur envoie un message. Toutefois, s'il en envoie cinq en mode hors connexion, vous n'obtiendrez qu'une seule synchronisation lorsqu'il se connectera. Si vous souhaitez créer cinq événements de synchronisation distincts, utilisez simplement des tags uniques.

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

Dans quel cas puis-je utiliser la synchronisation en arrière-plan ?

Idéalement, vous l'utiliseriez pour planifier l'envoi des 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, transferts de photos... tout ce que vous souhaitez communiquer au serveur, même si l'utilisateur quitte l'onglet ou le ferme. La page peut les stocker dans une "boîte d'envoi" et que le service worker les récupère et les envoie.

Mais vous pouvez aussi l'utiliser pour récupérer de petites données...

Encore une démonstration !

Voici la démo hors connexion Wikipédia que j'ai créée pour Supercharging Page Load (Booster le chargement de la page). 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. Déconnectez-vous (en utilisant le mode Avion ou avec un opérateur de téléphonie mobile de mauvaise qualité comme moi).
  3. Cliquez sur un lien vers un autre article.
  4. Un message vous informe que le chargement de la page a échoué. Ce message s'affiche également si le chargement de la page prend un peu de temps.
  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é.

À l'aide de ce modèle, l'utilisateur peut mettre son téléphone dans sa poche et continuer sa vie, en sachant que le téléphone lui alertera lorsqu'il le récupérera, ce qu'il veut.

Autorisations

Les démonstrations que j'ai présentées utilisent des notifications Web, qui nécessitent une autorisation, ce qui n'est pas le cas de la synchronisation en arrière-plan.

Les événements de synchronisation se terminent souvent lorsque l'utilisateur a ouvert une page sur le site. Par conséquent, exiger l'autorisation de l'utilisateur ne serait pas une bonne expérience. Au lieu de cela, nous limitons la période d'enregistrement et de déclenchement des synchronisations, afin d'éviter les abus. Exemple :

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

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 ne prennent en charge la synchronisation en arrière-plan, en particulier car Safari et Edge ne sont pas encore compatibles avec les service workers. Mais l'amélioration progressive aide ici:

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 utile d'utiliser la synchronisation en arrière-plan même si la connectivité de l'utilisateur semble bonne, car elle vous protège contre les navigations et la fermeture d'onglets lors de l'envoi de données.

L'avenir

Nous prévoyons de déployer la synchronisation en arrière-plan sur une version stable de Chrome au cours du premier semestre 2016, tout en travaillant sur une variante appelée "synchronisation périodique en arrière-plan". Avec la synchronisation périodique en arrière-plan, vous pouvez demander un événement limité par l'intervalle de temps, l'état de la batterie et l'état du réseau. Cela nécessiterait bien sûr l'autorisation de l'utilisateur, et c'est également au navigateur de déterminer quand et à quelle fréquence ces événements se déclenchent. En d'autres termes, un site d'actualités peut demander une synchronisation toutes les heures, mais le navigateur peut savoir que vous ne le consultez qu'à 07 h 00. La synchronisation se déclenchera donc tous les jours à 06 h 50. Cette idée est un peu plus loin que la synchronisation ponctuelle, mais elle arrive bientôt.

Progressivement, nous intégrons sur le Web des modèles Android et iOS populaires, tout en conservant ce qui fait le Web si beau.