Menyajikan audio dan video yang disimpan dalam cache

Ada beberapa hambatan dalam cara beberapa browser menangani permintaan untuk aset media—yaitu, URL yang ditentukan dalam atribut src dari elemen <video> dan <audio>—yang dapat menyebabkan perilaku penayangan yang salah, kecuali jika Anda melakukan langkah tertentu saat mengonfigurasi Workbox.

Permasalahan

Seluk-beluk masalah yang dimiliki browser seputar penayangan aset audio dan video dijelaskan secara mendetail dalam diskusi masalah GitHub ini. Gambaran lengkapnya memang rumit, tetapi poin utamanya adalah:

  • Workbox harus diberi tahu untuk mematuhi header permintaan Range dengan menggunakan modul workbox-range-requests ke strategi yang digunakan sebagai pengendali.
  • Elemen <video> atau <audio> harus diikutsertakan dalam mode CORS dengan atribut crossorigin.
  • Jika ingin menyajikan media dari cache, Anda harus menambahkannya secara eksplisit ke cache terlebih dahulu. Anda dapat melakukannya dengan precaching, atau dengan cache.add(), atau menggunakan metode warmStrategyCache di workbox-recipe. Menyimpan ke cache aset media saat di-streaming pada runtime tidak akan berfungsi karena hanya sebagian konten yang diambil dari jaringan selama pemutaran.

Berikut cara mengakomodasi persyaratan tersebut di Workbox, dimulai dengan markup yang tepat untuk aset media:

<!-- 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>

Kemudian, di pekerja layanan Anda, gunakan plugin workbox-range-request untuk menangani aset media sebagaimana mestinya:

// 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(),
    ],
  }),
);

Dengan pendekatan ini, Anda bisa memastikan bahwa aset media situs diambil dan di-cache oleh pekerja layanan, sambil mempertimbangkan permintaan rentang dan potensi jebakan lain yang terkait dengan permintaan media.