Catégories
Astuces et Design

Stratégies de mise en cache à l'ère des PWA – Une liste à part

Il était une fois, nous comptions sur les navigateurs pour gérer la mise en cache pour nous; en tant que développeurs à cette époque, nous avions très peu de contrôle. Mais vint ensuite les applications Web progressives (PWA), les travailleurs de service et l'API du cache – et soudain, nous avons un pouvoir étendu sur ce qui est placé dans le cache et comment il y est placé. Nous pouvons maintenant mettre en cache tout ce que nous voulons… et c'est là que réside un problème potentiel.

L'article continue ci-dessous

Les fichiers multimédias, en particulier les images, représentent la majeure partie du poids moyen des pages de nos jours, et la situation empire. Pour améliorer les performances, il est tentant de mettre en cache autant de contenu que possible, mais le devrions-nous? Dans la plupart des cas, non. Même avec toute cette nouvelle technologie à portée de main, de grandes performances reposent toujours sur une règle simple: ne demandez que ce dont vous avez besoin et faites chaque demande aussi petite que possible.

Pour offrir la meilleure expérience possible à nos utilisateurs sans abuser de leur connexion réseau ou de leur disque dur, il est temps de mettre à l'épreuve certaines des meilleures pratiques classiques, d'expérimenter les stratégies de mise en cache des médias et de jouer avec quelques astuces d'API de cache que les travailleurs du service ont caché leurs manches.

Toutes ces leçons que nous avons apprises en optimisant les pages Web pour l'accès à distance sont redevenues super utiles lorsque le mobile a décollé, et elles continuent d'être applicables dans le travail que nous faisons pour un public mondial aujourd'hui. Les connexions réseau non fiables ou à latence élevée sont toujours la norme dans de nombreuses régions du monde, nous rappelant qu'il n'est jamais sûr de supposer qu'une ligne de base technique augmente uniformément ou en synchronisation avec son bord de pointe correspondant. Et c'est ce qui se passe avec les meilleures pratiques en matière de performances: l'histoire a confirmé que les approches qui sont bonnes pour les performances aujourd'hui continueront d'être bonnes pour les performances à l'avenir.

Avant l'avènement des Service Workers, nous pouvions fournir des instructions aux navigateurs concernant la durée de mise en cache d'une ressource particulière, mais c'était à peu près tout. Les documents et ressources téléchargés sur la machine d'un utilisateur seraient déposés dans un répertoire sur leur disque dur. Lorsque le navigateur assemblait une demande pour un document ou un élément particulier, il regardait d'abord dans le cache pour voir s'il avait déjà ce dont il avait besoin pour éviter éventuellement de toucher le réseau.

Nous avons beaucoup plus de contrôle sur les requêtes réseau et le cache ces jours-ci, mais cela ne nous excuse pas de réfléchir aux ressources de nos pages Web.

Demandez uniquement ce dont vous avez besoin # section3

Comme je l'ai mentionné, le Web est aujourd'hui moche avec les médias. Les images et les vidéos sont devenues un moyen de communication dominant. Ils peuvent bien se convertir en termes de vente et de marketing, mais ils sont peu performants en termes de vitesse de téléchargement et de rendu. Dans cet esprit, chaque image (et vidéo, etc.) devrait avoir à se battre pour sa place sur la page.

Il y a quelques années, une de mes recettes a été incluse dans un article de journal sur la cuisine avec des spiritueux (alcool, pas fantômes). Je ne suis pas abonné à la version imprimée de ce document, donc lorsque l'article est sorti, je suis allé sur le site pour voir comment il s'est avéré. Lors d'une refonte récente, le site avait décidé de charger tous les articles dans une boîte de visualisation modale presque plein écran superposée sur leur page d'accueil. Cela signifiait demander l'article requis pour toutes les ressources associées à la page de l'article plus tous les contenus et actifs de la page d'accueil. Oh, et la page d'accueil avait des publicités vidéo – au pluriel. Et, oui, ils ont joué automatiquement.

J'ai ouvert DevTools et découvert que la page avait dépassé 15 Mo de poids de page. Tim Kadlec avait récemment lancé What Does My Site Cost?, Alors j'ai décidé de vérifier les dégâts. Il s’avère que le coût réel de consultation de cette page pour l’utilisateur moyen basé aux États-Unis était supérieur au coût de la version imprimée du journal de ce jour. C'est juste foiré.

Bien sûr, je pourrais blâmer les gens qui ont construit le site pour rendre un tel service à leurs lecteurs, mais la réalité est qu'aucun de nous ne va travailler dans le but d'aggraver l'expérience de nos utilisateurs. Cela pourrait arriver à n'importe lequel d'entre nous. Nous pourrions passer des jours à examiner les performances d'une page uniquement pour qu'un comité décide de placer cette page soigneusement conçue au-dessus d'un Times Square d'annonces vidéo à lecture automatique. Imaginez à quel point les choses seraient bien pires si nous empilions deux pages aux performances abyssales l'une sur l'autre!

Les médias peuvent être utiles pour attirer l'attention lorsque la concurrence est forte (par exemple, sur la page d'accueil d'un journal), mais lorsque vous souhaitez que les lecteurs se concentrent sur une seule tâche (par exemple, lire l'article réel), sa valeur peut passer de l'important à « agréable d'avoir." Oui, des études ont montré que les images excellaient à dessiner des globes oculaires, mais une fois qu'un visiteur est sur la page de l'article, personne ne s'en soucie; nous ne faisons que rendre le téléchargement plus long et l'accès plus coûteux. La situation ne fait qu'empirer lorsque nous insérons plus de médias dans la page.

Nous devons faire tout ce qui est en notre pouvoir pour réduire le poids de nos pages, afin d'éviter les demandes de choses qui n'ajoutent pas de valeur. Pour commencer, si vous écrivez un article sur une violation de données, résistez à l'envie d'inclure cette photo stock ridicule d'un mec aléatoire dans un sweat à capuche tapant sur un ordinateur dans une pièce très sombre.

Demandez le plus petit fichier possible # section4

Maintenant que nous avons fait le bilan de ce que nous faire devons inclure, nous devons nous poser une question cruciale: comment pouvons-nous le livrer de la manière la plus rapide possible? Cela peut être aussi simple que de choisir le format d'image le plus approprié pour le contenu présenté (et d'en optimiser le contenu) ou aussi complexe que de recréer des ressources entièrement (par exemple, si le passage de l'image raster à l'image vectorielle serait plus efficace).

Offrir des formats alternatifs # section5

En ce qui concerne les formats d'image, nous n'avons plus à choisir entre performances et portée. Nous pouvons fournir plusieurs options et laisser le navigateur décider lequel utiliser, en fonction de ce qu'il peut gérer.

Vous pouvez accomplir cela en offrant plusieurs sources dans un picture ou video élément. Commencez par créer plusieurs formats de l'élément multimédia. Par exemple, avec WebP et JPG, il est probable que le WebP aura une taille de fichier plus petite que le JPG (mais vérifiez pour vous en assurer). Avec ces sources alternatives, vous pouvez les déposer dans un picture comme ça:


  
  Texte descriptif sur l'image.

Navigateurs qui reconnaissent picture L'élément vérifiera la source avant de décider quelle image demander. Si le navigateur prend en charge le type MIME «image / webp», il lancera une demande d'image au format WebP. Sinon (ou si le navigateur ne reconnaît pas picture), il demandera le JPG.

La bonne chose à propos de cette approche est que vous fournissez la plus petite image possible à l'utilisateur sans avoir à recourir à une sorte de piratage JavaScript.

Vous pouvez adopter la même approche avec les fichiers vidéo:

Les navigateurs prenant en charge WebM demanderont le premier source, alors que les navigateurs qui ne comprennent pas les vidéos MP4, mais qui en comprennent, demanderont le second. Navigateurs qui ne prennent pas en charge le video L'élément reviendra au paragraphe sur le téléchargement du fichier.

L'ordre de votre source les éléments sont importants. Les navigateurs choisiront le premier utilisable source, donc si vous spécifiez un format alternatif optimisé après un format plus largement compatible, le format alternatif peut ne jamais être choisi.

Selon votre situation, vous pouvez envisager de contourner cette approche basée sur le balisage et de gérer les choses sur le serveur à la place. Par exemple, si un JPG est demandé et que le navigateur prend en charge WebP (qui est indiqué dans le Accept en-tête), rien ne vous empêche de répondre avec une version WebP de la ressource. En fait, certains services CDN – Cloudinary, par exemple – sont livrés avec ce type de fonctionnalité dès le départ.

Offrir différentes tailles # section6

Mis à part les formats, vous souhaiterez peut-être proposer d'autres tailles d'image optimisées pour la taille actuelle de la fenêtre d'affichage du navigateur. Après tout, il est inutile de charger une image 3 à 4 fois plus grande que l’écran qui la rend; c'est juste une perte de bande passante. C'est là que les images réactives entrent en jeu.

Voici un exemple:

Texte descriptif sur l'image.

Il se passe beaucoup de choses dans ce super-chargé img élément, donc je vais le décomposer:

  • Cette img offre trois options de taille pour un JPG donné: 256 px de large (small.jpg), 512 px de large (medium.jpg) et 1024 px de large (large.jpg). Ceux-ci sont fournis dans le srcset attribut avec descripteurs de largeur correspondants.
  • le src définit une source d'image par défaut, qui agit comme solution de rechange pour les navigateurs qui ne prennent pas en charge srcset. Votre choix pour l'image par défaut dépendra probablement du contexte et des modèles d'utilisation généraux. Souvent, je recommanderais que la plus petite image soit la valeur par défaut, mais si la majorité de votre trafic provient d'anciens navigateurs de bureau, vous souhaiterez peut-être utiliser l'image de taille moyenne.
  • le sizes L'attribut est un indice de présentation qui informe le navigateur de la façon dont l'image sera rendue dans différents scénarios (sa taille extrinsèque) une fois CSS appliqué. Cet exemple particulier indique que l'image sera sur toute la largeur de la fenêtre d'affichage (100vw) jusqu'à ce que la fenêtre atteigne 30 em de largeur (min-width: 30em), point auquel l'image aura une largeur de 30 em. Vous pouvez faire sizes valeur aussi compliquée ou aussi simple que vous le souhaitez; son omission oblige les navigateurs à utiliser la valeur par défaut de 100vw.

Vous pouvez même combiner cette approche avec des formats et des cultures alternatifs dans un seul picture. 🤯

Tout cela signifie que vous disposez d'un certain nombre d'outils pour fournir des supports à chargement rapide, alors utilisez-les!

Différer les demandes (si possible) # section7

Il y a des années, Internet Explorer 11 a introduit un nouvel attribut qui a permis aux développeurs de ne pas hiérarchiser img éléments pour accélérer le rendu des pages: lazyload. Cet attribut n'est jamais allé nulle part, en termes de normes, mais c'était une tentative solide de différer le chargement des images jusqu'à ce que les images soient en vue (ou proches) sans avoir à impliquer JavaScript.

Depuis lors, il y a eu d'innombrables implémentations JavaScript d'images de chargement paresseux, mais récemment, Google a également essayé une approche plus déclarative, en utilisant un attribut différent: loading.

le loading L'attribut prend en charge trois valeurs («auto», «paresseux» et «impatient») pour définir comment une ressource doit être importée. Pour nos besoins, la valeur «paresseux» est la plus intéressante car elle reporte le chargement de la ressource jusqu'à ce qu'elle atteigne une distance calculée de la fenêtre.

Ajoutant cela dans le mélange…

Texte descriptif sur l'image.

Cet attribut offre une amélioration des performances dans les navigateurs basés sur Chromium. J'espère que cela deviendra une norme et sera repris par d'autres navigateurs à l'avenir, mais en attendant, il n'y a aucun mal à l'inclure parce que les navigateurs qui ne comprennent pas l'attribut l'ignoreront simplement.

Cette approche complète très bien une stratégie de priorisation des médias, mais avant d'en arriver là, je veux examiner de plus près les travailleurs des services.

Manipuler les demandes dans un Service Worker # section8

Les Service Workers sont un type spécial de Web Worker avec la capacité d'intercepter, de modifier et de répondre à toutes les demandes réseau via l'API Fetch. Ils ont également accès à l'API Cache, ainsi qu'à d'autres magasins de données côté client asynchrones comme IndexedDB pour le stockage des ressources.

Lorsqu'un Service Worker est installé, vous pouvez vous connecter à cet événement et amorcer le cache avec les ressources que vous souhaitez utiliser ultérieurement. De nombreuses personnes utilisent cette opportunité pour écarter les copies des actifs globaux, y compris les styles, les scripts, les logos, etc., mais vous pouvez également l'utiliser pour mettre en cache les images à utiliser lorsque les demandes réseau échouent.

Gardez une image de secours dans votre poche arrière # section9

En supposant que vous souhaitez utiliser une solution de secours dans plusieurs recettes de mise en réseau, vous pouvez configurer une fonction nommée qui répondra avec cette ressource:

function respondWithFallbackImage() {
  return caches.match( "/i/fallbacks/offline.svg" );
}

Ensuite, dans un fetch gestionnaire d'événements, vous pouvez utiliser cette fonction pour fournir cette image de secours lorsque les demandes d'images échouent sur le réseau:

self.addEventListener( "fetch", event => {
  const request = event.request;
  if ( request.headers.get("Accept").includes("image") ) {
    event.respondWith(
      return fetch( request, { mode: 'no-cors' } )
        .then( response => {
          return response;
        })
        .catch(
          respondWithFallbackImage
        );
    );
  }
});

Lorsque le réseau est disponible, les utilisateurs obtiennent le comportement attendu:

Capture d'écran d'un composant montrant une série d'images de profil d'utilisateur d'utilisateurs qui ont aimé quelque chose
Les avatars des médias sociaux sont rendus comme prévu lorsque le réseau est disponible.

Mais lorsque le réseau est interrompu, les images seront automatiquement échangées contre un repli, et l'expérience utilisateur est toujours acceptable:

Capture d'écran montrant une série d'images utilisateur génériques identiques à la place des images individuelles qui n'ont pas été chargées
Un avatar de secours générique est rendu lorsque le réseau n'est pas disponible.

En apparence, cette approche peut ne pas sembler très utile en termes de performances, car vous avez essentiellement ajouté un téléchargement d'image supplémentaire dans le mix. Avec ce système en place, cependant, des opportunités assez incroyables s'ouvrent à vous.

Respecter le choix d'un utilisateur de sauvegarder les données # section10

Certains utilisateurs réduisent leur consommation de données en entrant dans un mode «léger» ou en activant une fonction «économiseur de données». Lorsque cela se produit, les navigateurs envoient souvent un Save-Data en-tête avec leurs demandes de réseau.

Au sein de votre technicien de service, vous pouvez rechercher cet en-tête et ajuster vos réponses en conséquence. Tout d'abord, vous recherchez l'en-tête:

let save_data = false;
if ( 'connection' in navigator ) {
  save_data = navigator.connection.saveData;
}

Ensuite, dans votre fetch gestionnaire d'images, vous pouvez choisir de répondre de manière préventive avec l'image de secours au lieu d'aller sur le réseau:

self.addEventListener( "fetch", event => {
  const request = event.request;
  if ( request.headers.get("Accept").includes("image") ) {
    event.respondWith(
      if ( save_data ) {
        return respondWithFallbackImage();
      }
      // code you saw previously
    );
  }
});

Vous pouvez même aller plus loin et régler respondWithFallbackImage() pour fournir des images alternatives en fonction de la demande d'origine. Pour ce faire, vous devez définir plusieurs solutions de secours à l'échelle mondiale dans le Service Worker:

const fallback_avatar = "/i/fallbacks/avatar.svg",
      fallback_image = "/i/fallbacks/image.svg";

Ces deux fichiers doivent ensuite être mis en cache lors de l'événement d'installation de Service Worker:

return cache.addAll( (
  fallback_avatar,
  fallback_image
));

Enfin, au sein de respondWithFallbackImage() vous pouvez diffuser l'image appropriée en fonction de l'URL récupérée. Dans mon site, les avatars sont tirés de Webmention.io, donc je teste cela.

function respondWithFallbackImage( url ) {
  const image = avatars.test( /webmention.io/ ) ? fallback_avatar
                                                 : fallback_image;
  return caches.match( image );
}

Avec ce changement, je devrai mettre à jour le fetch gestionnaire à passer request.url comme argument pour respondWithFallbackImage(). Une fois cela fait, lorsque le réseau est interrompu, je finis par voir quelque chose comme ça:

Capture d'écran montrant un commentaire de blog avec une image de profil utilisateur générique et un espace réservé d'image où le réseau n'a pas pu charger les images réelles
Une webmention qui contient à la fois un avatar et une image intégrée sera rendue avec deux solutions de rechange différentes lorsque l'en-tête Save-Data est présent.

Ensuite, nous devons établir des directives générales pour le traitement des ressources multimédias – en fonction de la situation, bien sûr.

La stratégie de mise en cache: prioriser certains médias # section11

D'après mon expérience, les médias – en particulier les images – sur le Web ont tendance à se diviser en trois catégories de nécessité. À une extrémité du spectre se trouvent des éléments qui n’apportent pas de valeur significative. À l'autre extrémité du spectre se trouvent des actifs critiques qui faire ajouter de la valeur, comme des tableaux et des graphiques qui sont essentiels pour comprendre le contenu environnant. Quelque part au milieu se trouvent ce que j'appellerais des médias «agréables à avoir». Ils faire ajouter de la valeur à l'expérience de base d'une page, mais ne sont pas essentiels à la compréhension du contenu.

Si vous considérez vos médias avec cette division à l'esprit, vous pouvez établir des directives générales pour la gestion de chacun, en fonction de la situation. En d'autres termes, une stratégie de mise en cache.

Stratégie de chargement des médias, décomposée par l'importance d'un atout pour comprendre une interface
Catégorie de média Connexion rapide Save-Data Connection lente Pas de réseau
Critique Charger le média Remplacer par un espace réservé
Agréable d'avoir Charger le média Remplacer par un espace réservé
Non critique Supprimer complètement du contenu

Quand il s'agit de lever l'ambiguïté de la critique du bon à avoir, il est utile d'avoir ces ressources organisées dans des répertoires séparés (ou similaires). De cette façon, nous pouvons ajouter une logique au Service Worker qui peut l'aider à décider laquelle est laquelle. Par exemple, sur mon propre site personnel, les images critiques sont auto-hébergées ou proviennent du site Web de mon livre. Sachant cela, je peux écrire des expressions régulières qui correspondent à ces domaines:

const high_priority = (
    /aaron-gustafson.com/,
    /adaptivewebdesign.info/
  );

Avec ça high_priority variable définie, je peux créer une fonction qui me fera savoir si une requête d'image donnée (par exemple) est une requête de haute priorité ou non:

function isHighPriority( url ) {
  // how many high priority links are we dealing with?
  let i = high_priority.length;
  // loop through each
  while ( i-- ) {
    // does the request URL match this regular expression?
    if ( high_priority(i).test( url ) ) {
      // yes, it’s a high priority request
      return true;
    }
  }
  // no matches, not high priority
  return false;
}

L'ajout de la prise en charge de la hiérarchisation des requêtes multimédias nécessite uniquement l'ajout d'une nouvelle condition dans le fetch gestionnaire d'événements, comme nous l'avons fait avec Save-Data. Votre recette spécifique pour la gestion du réseau et du cache sera probablement différente, mais voici comment j'ai choisi de mélanger cette logique dans les demandes d'images:

// Check the cache first
  // Return the cached image if we have one
  // If the image is not in the cache, continue

// Is this image high priority?
if ( isHighPriority( url ) ) {

  // Fetch the image
    // If the fetch succeeds, save a copy in the cache
    // If not, respond with an "offline" placeholder

// Not high priority
} else {

  // Should I save data?
  if ( save_data ) {

    // Respond with a "saving data" placeholder

  // Not saving data
  } else {

    // Fetch the image
      // If the fetch succeeds, save a copy in the cache
      // If not, respond with an "offline" placeholder
  }
}

Nous pouvons appliquer cette approche prioritaire à de nombreux types d'actifs. Nous pourrions même l'utiliser pour contrôler quelles pages sont servies en premier lieu par rapport au réseau.

La possibilité de contrôler quelles ressources sont mises en cache sur le disque est une énorme opportunité, mais elle comporte également une énorme responsabilité de ne pas en abuser.

Chaque stratégie de mise en cache est susceptible de différer, au moins un peu. Si nous publions un livre en ligne, par exemple, il peut être judicieux de mettre en cache tous les chapitres, images, etc. pour une consultation hors ligne. Le contenu est fixe et, en supposant qu’il n’y ait pas une tonne d’images et de vidéos volumineuses, les utilisateurs gagneront à ne pas avoir à télécharger chaque chapitre séparément.

Sur un site d'actualités, cependant, la mise en cache de chaque article et photo remplira rapidement les disques durs de nos utilisateurs. Si un site propose un nombre indéterminé de pages et d'éléments, c'est critique d'avoir une stratégie de mise en cache qui impose des limites strictes au nombre de ressources que nous mettons en cache sur le disque.

Une façon de procéder consiste à créer plusieurs blocs différents associés à la mise en cache de différentes formes de contenu. Les caches de contenu plus éphémères peuvent avoir des limites strictes quant au nombre d'éléments pouvant être stockés. Bien sûr, nous serons toujours liés aux limites de stockage de l'appareil, mais voulons-nous vraiment que notre site Web occupe 2 Go du disque dur de quelqu'un?

Voici un exemple, encore une fois sur mon propre site:

const sw_caches = {
  static: {
    name: `${version}static`
  },
  images: {
    name: `${version}images`,
    limit: 75
  },
  pages: {
    name: `${version}pages`,
    limit: 5
  },
  other: {
    name: `${version}other`,
    limit: 50
  }
}

Ici, j'ai défini plusieurs caches, chacune avec un name utilisé pour l'adresser dans l'API Cache et un version préfixe. le version est défini ailleurs dans le Service Worker et me permet de purger tous les caches à la fois si nécessaire.

À l'exception du static cache, qui est utilisé pour les actifs statiques, chaque cache a un limit au nombre d'articles qui peuvent être stockés. Par exemple, je ne cache que les 5 pages les plus récentes que quelqu'un a visitées. Les images sont limitées aux 75 plus récentes, etc. C'est une approche que Jeremy Keith décrit dans son livre fantastique Se déconnecter (que vous devriez vraiment lire si vous ne l'avez pas déjà fait — voici un exemple).

Une fois ces définitions de cache en place, je peux nettoyer régulièrement mes caches et tailler les éléments les plus anciens. Voici le code recommandé par Jeremy pour cette approche:

function trimCache(cacheName, maxItems) {
  // Open the cache
  caches.open(cacheName)
  .then( cache => {
    // Get the keys and count them
    cache.keys()
    .then(keys => {
      // Do we have more than we should?
      if (keys.length > maxItems) {
        // Delete the oldest item and run trim again
        cache.delete(keys(0))
        .then( () => {
          trimCache(cacheName, maxItems)
        });
      }
    });
  });
}

Nous pouvons déclencher l'exécution de ce code chaque fois qu'une nouvelle page se charge. En l'exécutant dans le Service Worker, il s'exécute dans un thread séparé et ne ralentit pas la réactivité du site. Nous le déclenchons en publiant un message (en utilisant postMessage()) au Service Worker à partir du thread JavaScript principal:

// First check to see if you have an active service worker
if ( navigator.serviceWorker.controller ) {
  // Then add an event listener
  window.addEventListener( "load", function(){
    // Tell the service worker to clean up
    navigator.serviceWorker.controller.postMessage( "clean up" );
  });
}

La dernière étape du câblage est de configurer le technicien de service pour recevoir le message:

addEventListener("message", messageEvent => {
  if (messageEvent.data == "clean up") {
    // loop though the caches
    for ( let key in sw_caches ) {
      // if the cache has a limit
      if ( sw_caches(key).limit !== undefined ) {
        // trim it to that limit
        trimCache( sw_caches(key).name, sw_caches(key).limit );
      }
    }
  }
});

Ici, le Service Worker écoute les messages entrants et répond à la demande de «nettoyage» en exécutant trimCache() sur chacun des compartiments de cache avec un défini limit.

Cette approche n'est en aucun cas élégante, mais elle fonctionne. Il serait préférable de prendre des décisions sur la purge des réponses mises en cache en fonction de la fréquence d'accès à chaque élément et / ou de la place qu'il occupe sur le disque. (Supprimer les éléments mis en cache uniquement en fonction de leur date de mise en cache n'est pas aussi utile.) Malheureusement, nous n'avons pas ce niveau de détail en ce qui concerne l'inspection des caches… pour l'instant. Je travaille actuellement pour résoudre cette limitation dans l'API Cache en ce moment.

Vos utilisateurs passent toujours en premier # section13

Les technologies sous-jacentes aux applications Web progressives continuent de mûrir, mais même si vous n'êtes pas intéressé à transformer votre site en PWA, vous pouvez faire tant de choses aujourd'hui pour améliorer l'expérience de vos utilisateurs en matière de médias. Et, comme pour toute autre forme de conception inclusive, cela commence par se concentrer sur vos utilisateurs qui sont les plus à risque d'avoir une expérience horrible.

Faites des distinctions entre les médias critiques, agréables à utiliser et superflus. Retirez la loupe, puis optimisez le bejeezus de chaque actif restant. Servez vos médias dans plusieurs formats et tailles, en priorité les plus petites versions pour tirer le meilleur parti d'une latence élevée et de connexions lentes. Si vos utilisateurs disent qu'ils souhaitent enregistrer des données, respectez cela et mettez en place un plan de secours. Cachez judicieusement et avec le plus grand respect pour l'espace disque de vos utilisateurs. Et, enfin, auditez régulièrement vos stratégies de mise en cache, en particulier en ce qui concerne les fichiers multimédias volumineux.Suivez ces directives, et chacun de vos utilisateurs, des gens qui font basculer un JioPhone sur un réseau mobile rural en Inde aux personnes qui jouent sur un jeu haut de gamme. portable connecté à une ligne de fibre optique de 10 Gbit / s dans la Silicon Valley, je vous en remercie.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *