La vidéo est un élément difficile à gérer : le streaming nécessite beaucoup de bande passante et la mise en cache n'est pas simple. Ces problèmes sont amplifiés lorsque les vidéos sont lues en boucle, comme sur un écran de borne interactive. Par exemple, si une entreprise dispose de centaines d'appareils qui diffusent 30 vidéos en boucle toute la journée, tous les jours, son réseau pourrait rapidement être saturé. En diffusant les vidéos à partir du cache au lieu de les diffuser en streaming, vous n'êtes facturé qu'une seule fois pour le téléchargement. Les lectures suivantes sont plus rapides et les vidéos peuvent être lues hors connexion. Pour ce faire, vous pouvez tirer parti des capacités de stockage du navigateur, dont l'API Cache Storage et IndexedDB sont les plus adaptées au stockage de fichiers vidéo. Bien que les deux soient de bonnes options, nous nous concentrerons sur l'API Cache Storage pour son intégration à la bibliothèque service worker populaire Workbox.
Mettre en cache des vidéos à partir d'un service worker
Étant donné que le téléchargement et la mise en cache de ressources volumineuses telles que des vidéos peuvent être des tâches particulièrement gourmandes en temps et en ressources processeur, vous devez les effectuer en arrière-plan, en dehors du thread principal. Les service workers sont particulièrement utiles pour décharger les tâches de mise en cache. Ils agissent comme un proxy entre la page et le réseau, ce qui leur permet d'intercepter les requêtes et d'appliquer une logique supplémentaire à la réponse du réseau (par exemple, une stratégie de mise en cache).
Il existe de nombreuses stratégies de mise en cache différentes, chacune étant conçue pour aider dans différents cas d'utilisation. Par exemple, pour diffuser un fichier à partir d'un cache s'il est disponible, ou revenir au réseau dans le cas contraire, vous pouvez écrire le code suivant.
self.addEventListener('fetch', function (event) { event.respondWith( caches.match(event.request).then(function (response) { return response || fetch(event.request); }), ); });
La gestion de ce processus pour différents types d'assets ou URL nécessitant différentes stratégies de mise en cache peut être répétitive et sujette aux erreurs. Workbox fournit un ensemble d'outils, y compris des helpers de routage et des stratégies de mise en cache, qui vous permettent d'écrire du code de service worker de manière plus déclarative et réutilisable.
La stratégie précédente est appelée cache first. Pour écrire la même chose avec Workbox, vous devez inclure ce qui suit :
registerRoute( ({ request }) => request.destination === 'video', new CacheFirst() );
Workbox fournit des recettes similaires pour d'autres stratégies de mise en cache et des tâches courantes de service worker, y compris l'intégration aux outils de compilation tels que Webpack et Rollup.
Une fois Workbox configuré, vous devez choisir le moment où vous allez mettre en cache vos vidéos. Deux approches sont possibles : de manière anticipée au chargement de la page ou de manière différée lorsque la vidéo est demandée.
Approche eager
Le pré-cache est une technique qui consiste à enregistrer des fichiers dans le cache lors de l'installation du service worker, ce qui les rend disponibles dès que le service worker l'est. Workbox peut configurer automatiquement le pré-cache pour les fichiers auxquels il peut accéder lors de votre processus de compilation.
Le code Workbox suivant peut être utilisé dans votre service worker pour précharger des fichiers :
import { addPlugins, precacheAndRoute } from 'workbox-precaching'; import { RangeRequestsPlugin } from 'workbox-range-requests'; addPlugins([new RangeRequestsPlugin()]); precacheAndRoute(self.__WB_MANIFEST);
import(s) : chargez les liaisons requises à partir des modules Workbox correspondants. Étant donné que les service workers ne sont pas encore compatibles avec les ESModules de manière universelle, votre service worker optimisé par Workbox devra être transmis via un bundler pour fonctionner en production.RangeRequestsPlugin: permet à une requête avec un en-têteRanged'être traitée par une réponse mise en cache. Cela est nécessaire, car les navigateurs utilisent généralement un en-têteRangepour le contenu multimédia.addPlugins: vous permet d'ajouter des plug-ins Workbox à chaque requête Workbox.precacheAndRoute: ajoute des entrées à la liste de précache et crée une route pour gérer les requêtes de récupération correspondantes.__WB_MANIFEST: espace réservé que la CLI Workbox (ou les plug-ins d'outil de compilation) remplace par le fichier manifeste du précache.
Transmettez votre service worker à la CLI Workbox ou à l'outil de compilation de votre choix, et configurez la façon dont votre précache doit être généré. Un fichier workbox-config.js, comme celui ci-dessous, indiquera à la CLI comment afficher votre service worker :
module.exports = { globDirectory: '.', globPatterns: ['**/*.{html,mp4}'], maximumFileSizeToCacheInBytes: 5000000, swSrc: 'sw.js', swDest: 'sw.js', };
globDirectory: dossier racine à partir duquel commencer la recherche des fichiers de précacheglobPatterns: modèles de fichier (globs) à précharger en cache.maximumFileSizeToCacheInBytes: limite supérieure de la taille d'un fichier pouvant être préchargé dans le cache, en octets.swSrc: emplacement du fichier qui sera utilisé pour générer votre service worker.swDest: destination du service worker généré (peut être identique au fichier source, mais assurez-vous queself.__WB_MANIFESTest présent pour chaque exécution).
Lorsque le processus de compilation s'exécute, une nouvelle version du service worker est générée et self.__WB_MANIFEST est remplacé par une liste de fichiers, chacun avec un hachage pour indiquer sa révision :
precacheAndRoute([ { revision: '524ac4b453c83f76eb9caeec11854ca5', url: 'ny.mp4', }, ]);
Chaque fois que le processus de compilation s'exécute, cette liste est réécrite avec l'ensemble actuel des fichiers correspondants et leurs hachages de révision actuels. Cela garantit que chaque fois qu'un fichier est ajouté, supprimé ou modifié, le service worker met à jour le cache lors de sa prochaine installation.
Approche différée
Lorsque vous ne disposez pas de toutes les vidéos au moment de la compilation ou que vous ne souhaitez mettre en cache les vidéos que lorsque vous en avez besoin, vous devez adopter une approche différée. Cette approche nécessite de séparer la mise en cache et la diffusion. En effet, seuls des contenus partiels sont récupérés sur le réseau lors de la lecture de la vidéo. La mise en cache des fichiers lors de la diffusion en streaming ne fonctionnera donc pas.
Mise en cache des fichiers
Les caches peuvent être créés à l'aide de Cache.open(), puis des fichiers peuvent être ajoutés au cache à l'aide de Cache.add() ou Cache.addAll(). Si votre application reçoit une liste JSON de vidéos à mettre en cache, elles peuvent être ajoutées à un cache vidéo comme suit :
// Open video cache const cache = await caches.open('video-cache'); // Fetch list of videos const videos = await (await fetch('/video-list.json')).json(); // Add videos to cache await cache.addAll(videos);
L'avantage de cette approche est que vous pouvez contrôler l'étape de mise en cache indépendamment du cycle de vie du service worker, même à partir d'autres Web Workers. L'inconvénient est que la gestion du stockage incombe au développeur : vous devez écrire votre propre algorithme pour suivre les modifications apportées aux fichiers, suivre les fichiers actuellement mis en cache dans le navigateur et gérer les mises à jour des fichiers pour vous assurer que seuls les fichiers modifiés sont mis à jour.
Diffuser des fichiers vidéo mis en cache
Une stratégie de mise en cache du runtime de service worker, comme cache first, peut ensuite être utilisée pour diffuser les fichiers vidéo précédemment mis en cache :
import { registerRoute } from 'workbox-routing'; import { CacheFirst } from 'workbox-strategies'; import { CacheableResponsePlugin } from 'workbox-cacheable-response'; import { RangeRequestsPlugin } from 'workbox-range-requests'; registerRoute( ({ request }) => request.destination === 'video', new CacheFirst({ cacheName: 'video-cache', plugins: [ new CacheableResponsePlugin({ statuses: [200], }), new RangeRequestsPlugin(), ], }), );
import(s) : charge les liaisons requises à partir des modules Workbox correspondants.registerRoute: achemine les requêtes vers des fonctions (stratégies de mise en cache et plug-ins) qui fournissent des réponses.CacheFirst: stratégie de mise en cache qui répond à la requête à partir du cache, si disponible, ou la récupère à partir du réseau et met à jour le cache.CacheableResponsePlugin: permet d'indiquer les en-têtes qui doivent être présents pour que la réponse puisse être mise en cache. Veillez à n'inclure que 200 états pour la mise en cache des vidéos afin d'éviter que les réponses de contenu partiel (206) ne soient mises en cache lors du streaming des vidéos.RangeRequestsPlugin: plug-in qui permet à une requête avec un en-têteRanged'être traitée par une réponse mise en cache. Cela est nécessaire, car les navigateurs utilisent généralement un en-têteRangepour le contenu multimédia.
L'optimisation du chargement des vidéos est une tâche importante pour les applications qui effectuent du streaming intensif. En tirant parti de l'API Cache Storage du navigateur et de Workbox, vous pouvez rendre cette tâche autrement difficile gérable, économiser la bande passante de vos utilisateurs, réduire la charge du serveur, accélérer la lecture des vidéos et permettre à vos vidéos de s'exécuter même hors connexion.