Há algumas falhas na forma como alguns navegadores lidam com solicitações de recursos de mídia, ou seja, o URL especificado no atributo src
dos elementos <video>
e <audio>
, o que pode levar a um comportamento de exibição incorreto, a menos que você siga etapas específicas ao configurar a caixa de trabalho.
O problema
As complexidades do problema que os navegadores enfrentam em relação à disponibilização de recursos de áudio e vídeo são explicadas em detalhes nesta discussão do problema do GitHub (link em inglês). O panorama completo é complicado, mas os pontos principais são:
- A caixa de trabalho precisa ser informada para respeitar os cabeçalhos de solicitação
Range
usando o móduloworkbox-range-requests
na estratégia usada como gerenciador. - Os elementos
<video>
ou<audio>
precisam ativar o modo CORS com o atributocrossorigin
. - Para exibir mídia do cache, adicione-a explicitamente a ele com antecedência. Para isso, faça o pré-armazenamento em cache, use
cache.add()
ou use o método HeatStrategyCache em receitas de caixas de trabalho. O armazenamento em cache do recurso de mídia durante a transmissão no ambiente de execução não funcionará, já que somente conteúdo parcial é buscado na rede durante a reprodução.
Veja como atender a esses requisitos no Workbox, começando com a marcação adequada para um recurso de mí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>
Em seguida, no service worker, use o plug-in workbox-range-request
para processar os recursos de mídia corretamente:
// 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(),
],
}),
);
Com essa abordagem, você pode garantir que os recursos de mídia do seu site sejam corretamente buscados e armazenados em cache pelo service worker, considerando as solicitações de intervalo e outras armadilhas relacionadas às solicitações de mídia.