La façon dont certains navigateurs traitent les requêtes d'éléments multimédias (l'URL spécifiée dans l'attribut src
des éléments <video>
et <audio>
) peut rendre la diffusion incorrecte, sauf si vous prenez des mesures spécifiques lors de la configuration de Workbox.
Problème
Les subtilités des problèmes que rencontrent les navigateurs pour diffuser des assets audio et vidéo sont expliqués en détail dans cette discussion sur GitHub. La situation dans son ensemble est complexe, mais les points clés sont les suivants:
- Il faut indiquer à Workbox de respecter les en-têtes de requête
Range
en utilisant le moduleworkbox-range-requests
pour la stratégie utilisée en tant que gestionnaire. - Les éléments
<video>
ou<audio>
doivent activer le mode CORS avec l'attributcrossorigin
. - Si vous souhaitez diffuser des contenus multimédias à partir du cache, vous devez les y ajouter explicitement à l'avance. Pour ce faire, vous pouvez effectuer une mise en cache préalable, avec
cache.add()
ou utiliser la méthode hotStrategyCache dans le fichier "Workbox-recipes". La mise en cache de l'asset multimédia lors de sa diffusion en streaming au moment de l'exécution ne fonctionne pas, car seule une partie du contenu est extraite du réseau pendant la lecture.
Voici comment répondre à ces exigences dans Workbox, en commençant par le balisage approprié pour un asset multimédia:
<!-- In your page: -->
<!-- You need to set `crossorigin`, even for same-origin URLs! -->
<video src="movie.mp4" crossorigin="anonymous"></video>
<audio src="song.mp3" crossorigin="anonymous"></audio>
Ensuite, dans votre service worker, utilisez le plug-in workbox-range-request
pour gérer les éléments multimédias en conséquence:
// sw.js
import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';
import {RangeRequestsPlugin} from 'workbox-range-requests';
// In your service worker:
// It's up to you to either precache, use warmRuntimeCache, or
// explicitly call cache.add() to populate the cache with media assets.
// If you choose to cache media assets up front, do so with care,
// as they can be quite large and exceed storage quotas.
//
// This route will go to the network if there isn't a cache match,
// but it won't populate the cache at runtime because the response for
// the media asset will be a partial 206 response. If there is a cache
// match, then it will properly serve partial responses.
registerRoute(
({request}) => {
const {destination} = request;
return destination === 'video' || destination === 'audio'
},
new CacheFirst({
cacheName: 'your-cache-name-here',
plugins: [
new CacheableResponsePlugin({
statuses: [200]
}),
new RangeRequestsPlugin(),
],
}),
);
Cette approche vous permet de vous assurer que les éléments multimédias de votre site Web sont correctement récupérés et mis en cache par votre service worker, tout en prenant en compte les requêtes de plage et les autres pièges potentiels liés aux requêtes multimédias.