提供快取的音訊和視訊

部分瀏覽器在處理媒體素材資源請求的方式 (也就是 <video><audio> 元素的 src 屬性中指定的網址) 有些不同,因此除非您在設定 Workbox 時採取特定步驟,否則可能會導致放送行為不正確。

問題

如要進一步瞭解瀏覽器提供音訊和影片素材資源的細節,請參閱這個 GitHub 問題討論。細節相當複雜,但重點如下:

  • 必須透過做為處理常式使用的策略,使用 workbox-range-requests 模組告知 Workbox 遵循 Range 要求標頭
  • <video><audio> 元素必須透過 crossorigin 屬性選擇使用 CORS 模式。
  • 如要透過快取提供媒體,您必須事先將媒體明確加入快取中。您可以透過預先快取、使用 cache.add(),或在 Workbox 方案中使用暖 StrategyCache 方法的方式來執行此操作。由於在播放過程中只會從網路擷取部分內容,因此在執行階段中串流的媒體素材資源無法快取。

以下說明如何在 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(),
    ],
  }),
);

透過這種方式,您可以確保服務工作處理程序正確擷取及快取網站媒體資產,同時將範圍要求和其他可能與媒體要求相關的錯誤納入考量。