I video sono asset difficili da gestire: lo streaming richiede molta larghezza di banda e la memorizzazione nella cache non è semplice. Questi problemi si aggravano quando i video vengono riprodotti in loop, ad esempio in un display di un chiosco. Se, ad esempio, un'azienda ha centinaia di dispositivi che riproducono 30 video in loop tutto il giorno, tutti i giorni, la rete potrebbe sovraccaricarsi rapidamente. Se i video vengono pubblicati dalla cache anziché riprodotti in streaming, il costo del download viene sostenuto una sola volta, le riproduzioni successive sono più veloci e i video sono disponibili per la riproduzione offline. Per farlo, puoi sfruttare le funzionalità di archiviazione del browser, di cui l'API Cache Storage e IndexedDB sono le più adatte per archiviare i file video. Sebbene entrambe siano buone opzioni, ci concentreremo sull'API Cache Storage per la sua integrazione con la popolare libreria service worker Workbox.
Memorizzazione nella cache di video da un service worker
Poiché il download e la memorizzazione nella cache di asset di grandi dimensioni come i video possono essere un'attività particolarmente dispendiosa in termini di tempo e processore, è consigliabile eseguirla in background al di fuori del thread principale. I service worker sono particolarmente utili per scaricare le attività di memorizzazione nella cache. Funge da proxy tra la pagina e la rete, consentendo di intercettare le richieste e applicare una logica aggiuntiva alla risposta della rete, ad esempio una strategia di memorizzazione nella cache.
Esistono molte strategie di memorizzazione nella cache diverse e ognuna è progettata per essere utile in casi d'uso diversi. Ad esempio, per pubblicare un file da una cache, se disponibile, o eseguire il fallback alla rete in caso contrario, puoi scrivere il seguente codice.
self.addEventListener('fetch', function (event) { event.respondWith( caches.match(event.request).then(function (response) { return response || fetch(event.request); }), ); });
La gestione di questo aspetto per diversi tipi di asset o URL che richiedono strategie di memorizzazione nella cache diverse può essere un processo ripetitivo e soggetto a errori. Workbox fornisce un insieme di strumenti, tra cui helper di routing e strategie di memorizzazione nella cache, che ti consentono di scrivere codice service worker in modo più dichiarativo e riutilizzabile.
La strategia precedente è chiamata cache first. Per scrivere la stessa cosa utilizzando Workbox, devi includere quanto segue:
registerRoute( ({ request }) => request.destination === 'video', new CacheFirst() );
Workbox fornisce ricette simili per altre strategie di memorizzazione nella cache e attività comuni dei service worker, inclusa l'integrazione con strumenti di build come Webpack e Rollup.
Una volta configurata Workbox, devi scegliere quando memorizzare nella cache i video. In questo caso, esistono due approcci: in modo eager al caricamento della pagina o in modo lazy quando viene richiesto il video.
Approccio eager
Il precaching è una tecnica in cui i file vengono salvati nella cache durante l'installazione del service worker, rendendoli disponibili non appena il service worker è pronto. Workbox può configurare automaticamente il precaching per i file a cui può accedere durante il processo di build.
Il seguente codice Workbox può essere utilizzato nel service worker per prememorizzare i file nella cache:
import { addPlugins, precacheAndRoute } from 'workbox-precaching'; import { RangeRequestsPlugin } from 'workbox-range-requests'; addPlugins([new RangeRequestsPlugin()]); precacheAndRoute(self.__WB_MANIFEST);
import(s) - Carica i binding richiesti dai moduli Workbox corrispondenti. Poiché i service worker non supportano ancora universalmente ESModules, il service worker basato su Workbox dovrà essere passato attraverso un bundler per funzionare in produzione.RangeRequestsPlugin: consente a una richiesta con un'intestazioneRangedi essere soddisfatta da una risposta memorizzata nella cache. Questo è necessario perché i browser in genere utilizzano un'intestazioneRangeper i contenuti multimediali.addPlugins: consente di aggiungere plug-in Workbox a ogni richiesta di Workbox.precacheAndRoute: aggiunge voci all'elenco di pre-cache e crea una route per gestire le richieste di recupero corrispondenti.__WB_MANIFEST: un segnaposto che la CLI Workbox (o i plug-in degli strumenti di compilazione) sostituisce con il manifest di pre-cache.
Passa il service worker alla CLI Workbox o allo strumento di build che preferisci e configura la modalità di generazione della precache. Un file workbox-config.js, come il seguente,indicherà alla CLI come deve eseguire il rendering del service worker:
module.exports = { globDirectory: '.', globPatterns: ['**/*.{html,mp4}'], maximumFileSizeToCacheInBytes: 5000000, swSrc: 'sw.js', swDest: 'sw.js', };
globDirectory: la cartella principale da cui iniziare a cercare i file di pre-memorizzazione nella cacheglobPatterns: i pattern dei file ("glob") che devono essere memorizzati nella cache preliminare.maximumFileSizeToCacheInBytes: un limite superiore per le dimensioni di un file da prememorizzare nella cache, espresso in byte.swSrc: la posizione del file che verrà utilizzato per generare il service worker.swDest: la destinazione del service worker generato (può essere la stessa del file di origine, ma assicurati cheself.__WB_MANIFESTsia presente per ogni esecuzione).
Quando viene eseguito il processo di build, viene generata una nuova versione del service worker e self.__WB_MANIFEST viene sostituito da un elenco di file, ognuno con un hash per indicare la revisione:
precacheAndRoute([ { revision: '524ac4b453c83f76eb9caeec11854ca5', url: 'ny.mp4', }, ]);
Ogni volta che viene eseguito il processo di compilazione, questo elenco viene riscritto con il set corrente di file corrispondenti e i relativi hash di revisione correnti. In questo modo, ogni volta che un file viene aggiunto, rimosso o modificato, il service worker aggiornerà la cache alla successiva installazione.
Approccio lazy
Se non hai tutti i video disponibili al momento della creazione o vuoi memorizzare nella cache i video solo quando sono necessari, devi adottare un approccio lazy. Questo approccio richiede la separazione della memorizzazione nella cache e della pubblicazione, perché durante la riproduzione video viene recuperato dalla rete solo il contenuto parziale, quindi la memorizzazione nella cache dei file durante lo streaming non funziona.
Memorizzazione nella cache dei file
Le cache possono essere create utilizzando Cache.open(), quindi i file possono essere aggiunti alla cache utilizzando Cache.add() o Cache.addAll(). Se la tua app riceve un elenco JSON di video da memorizzare nella cache, questi possono essere aggiunti a una cache video nel seguente modo:
// Open video cache const cache = await caches.open('video-cache'); // Fetch list of videos const videos = await (await fetch('/video-list.json')).json(); // Add videos to cache await cache.addAll(videos);
Il vantaggio di questo approccio è che puoi controllare il passaggio di memorizzazione nella cache indipendentemente dal ciclo di vita del service worker, anche da altri web worker. Lo svantaggio è che la gestione dello spazio di archiviazione dipende dallo sviluppatore: devi scrivere il tuo algoritmo per monitorare le modifiche ai file, tenere traccia dei file attualmente memorizzati nella cache del browser e gestire gli aggiornamenti dei file per assicurarti che vengano aggiornati solo i file modificati.
Pubblicazione di file video memorizzati nella cache
Una strategia di memorizzazione nella cache in fase di runtime del service worker, come cache first, può quindi essere utilizzata per pubblicare i file video memorizzati nella cache in precedenza:
import { registerRoute } from 'workbox-routing'; import { CacheFirst } from 'workbox-strategies'; import { CacheableResponsePlugin } from 'workbox-cacheable-response'; import { RangeRequestsPlugin } from 'workbox-range-requests'; registerRoute( ({ request }) => request.destination === 'video', new CacheFirst({ cacheName: 'video-cache', plugins: [ new CacheableResponsePlugin({ statuses: [200], }), new RangeRequestsPlugin(), ], }), );
import(s) - Carica i binding richiesti dai moduli workbox corrispondenti.registerRoute: indirizza le richieste alle funzioni (strategie di memorizzazione nella cache e plug-in) che forniscono risposte.CacheFirst: strategia di memorizzazione nella cache che soddisfa la richiesta dalla cache, se disponibile, altrimenti la recupera dalla rete e aggiorna la cache.CacheableResponsePlugin: utilizzato per indicare quali intestazioni devono essere presenti affinché la risposta sia memorizzabile nella cache. Assicurati di includere solo 200 stati per la memorizzazione nella cache dei video delle route per evitare che le risposte parziali dei contenuti (206) vengano memorizzate nella cache durante lo streaming dei video.RangeRequestsPlugin: plug-in che consente di soddisfare una richiesta con un'intestazioneRangetramite una risposta memorizzata nella cache. Questo è necessario perché i browser in genere utilizzano un'intestazioneRangeper i contenuti multimediali.
L'ottimizzazione del caricamento dei video è un'attività importante per le app che eseguono streaming intensivo. Sfruttando l'API Cache Storage e Workbox del browser, puoi rendere gestibile questa attività altrimenti difficile, risparmiando la larghezza di banda degli utenti, riducendo il carico del server, ottenendo una riproduzione video più rapida e consentendo la riproduzione dei video anche offline.