מציג וידאו ואודיו שנשמרו במטמון

יש כמה קמטים באופן שבו דפדפנים מסוימים מטפלים בבקשות לנכסי מדיה – כלומר, כתובת ה-URL שצוינה במאפיין src של רכיבי <video> ו-<audio> – ומצבים כאלה עלולים להוביל להתנהגות שגויה של הצגת המודעות אלא אם ינקטו פעולות ספציפיות במהלך ההגדרה של תיבת העבודה.

הבעיה

בדיון הזה על בעיות ב-GitHub מוסבר בהרחבה על המורכבות של הבעיות שגורמות לדפדפנים להציג נכסי וידאו ואודיו. התמונה המלאה מורכבת, אך הנקודות העיקריות הן:

  • צריך להנחות את תיבת העבודה לכבד כותרות בקשות של Range באמצעות המודול workbox-range-requests לשיטה שמשמשת כ-handler.
  • רכיבי <video> או <audio> צריכים לעבור למצב CORS עם המאפיין crossorigin.
  • אם רוצים להציג מדיה מהמטמון, צריך להוסיף אותה מראש למטמון באופן מפורש. אפשר לעשות זאת על ידי שליחה מראש במטמון, באמצעות cache.add() או באמצעות השיטה hotStrategyCache במתכונים של תיבת עבודה. לא תוכלו לשמור במטמון את נכס המדיה בזמן שהוא משודר בזמן הריצה, כי במהלך ההפעלה רק תוכן חלקי מאוחזר מהרשת.

כך אפשר להתאים לדרישות האלה ב-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>

לאחר מכן, ב-Service Worker, משתמשים בפלאגין 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(),
    ],
  }),
);

כך תוכלו להבטיח שנכסי המדיה באתר יאוחזרו כראוי ויישמרו במטמון על ידי קובץ השירות (service worker), תוך התחשבות בבקשות לטווח ובטעויות פוטנציאליות אחרות הקשורות לבקשות מדיה.