Есть некоторые недостатки в том, как некоторые браузеры обрабатывают запросы на мультимедийные ресурсы, то есть URL-адрес, указанный в атрибуте src
элементов <video>
и <audio>
, что может привести к некорректному поведению при обслуживании, если вы не предпримете определенные шаги при настройке Workbox.
Проблема
Тонкости проблем, с которыми сталкиваются браузеры при обслуживании аудио- и видеоресурсов, подробно объясняются в этом обсуждении проблемы на GitHub . Полная картина сложна, но ключевые моменты таковы:
- Workbox необходимо указать, чтобы он уважал заголовки запросов
Range
, используя модульworkbox-range-requests
для стратегии, используемой в качестве обработчика. - Элементы
<video>
или<audio>
должны включить режим CORS с помощью атрибутаcrossorigin
. - Если вы хотите обслуживать медиафайлы из кеша, вам следует заранее явно добавить их в кеш. Вы можете сделать это с помощью предварительного кэширования, с помощью
cache.add()
или с помощью метода WarmStrategyCache в рецептах рабочего ящика. Кэширование медиа-ресурса во время его потоковой передачи во время выполнения не будет работать, поскольку во время воспроизведения из сети извлекается только частичный контент.
Вот как удовлетворить эти требования в Workbox, начиная с правильной разметки для медиаресурса:
<!-- 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>
Затем в своем сервисном работнике используйте плагин workbox-range-request
для соответствующей обработки медиа-ресурсов:
// 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(),
],
}),
);
Используя этот подход, вы можете гарантировать, что медиа-ресурсы вашего веб-сайта правильно извлекаются и кэшируются вашим сервисным работником, принимая во внимание запросы диапазона и другие потенциальные ошибки, связанные с медиа-запросами.