Menyajikan audio dan video yang disimpan dalam cache

Ada beberapa kendala terkait cara beberapa browser menangani permintaan 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-langkah tertentu saat mengonfigurasi Workbox.

Permasalahan

Seluk-beluk masalah browser terkait penayangan aset audio dan video dijelaskan secara mendetail dalam diskusi masalah GitHub ini. Gambaran lengkapnya 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 mengaktifkan mode CORS dengan atribut crossorigin.
  • Jika ingin menyajikan media dari cache, Anda harus menambahkannya secara eksplisit ke cache terlebih dahulu. Anda dapat melakukannya dengan precache, atau dengan cache.add(), atau dengan menggunakan metode warmStrategyCache dalam resep kotak kerja. Menyimpan aset media ke dalam cache saat di-streaming saat runtime tidak akan berfungsi, karena hanya sebagian konten yang diambil dari jaringan selama pemutaran.

Berikut cara mengakomodasi persyaratan ini 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 disimpan dalam cache dengan benar oleh pekerja layanan, sekaligus mempertimbangkan permintaan rentang dan potensi masalah lainnya yang terkait dengan permintaan media.