caching - 具有范围请求插件 : cannot fetch mp3 files when offline 的服务 worker

标签 caching audio service-worker firebase-hosting workbox

我正在开发一个需要离线提供所有内容的单页 PWA。

初始设置和问题:
我使用 create-react-app 来设置基础,然后使用 react-app-rewired 将 GenerateSW 插件替换为 InjectManifest 并在我的 service worker 中对 webpack 生成的 list 进行简单的 precacheAndRoute。

工作就像一个魅力,除了我的 mp3 文件:在 Safari 中,我看不到轨道的持续时间,进度条已经死了。在 Chrome 中它或多或少没问题,唯一的问题是它会在播放音频文件时切断最后 1-2 秒。

初步解决方案:在我的 SW 配置中,我为使用范围请求插件的 mp3 文件添加了一个特定的 registerRoute,根据 https://developers.google.com/web/tools/workbox/guides/advanced-recipes#cached-av .它有点工作,现在只要我在线,Chrome 和 Safari 都可以正常工作。当我离线时,除了 mp3 文件之外的所有内容都可以从缓存中获取。

你可以看到她的错误:https://cgl-hunter-kids-test.firebaseapp.com/
点击标题图片进入网站,在左上角菜单中选择“历史”,然后选择9个可用故事中的任何一个。音频播放器位于右上角。

在 Chrome 开发工具中,我可以看到它在线时从 Service Worker 获取 mp3 文件。我还可以看到 mp3 文件确实存在于预缓存中。我不知道为什么离线时找不到它们-有人可以帮忙吗?

谢谢,
戴安娜

我的服务人员配置:

const COOKIE_CONSENT_ENDPOINT = '/hunterkidsCookieConsent';
const GAME_DATA_ENDPOINT      = '/hunterkidsGameData';

/* Use client claim to handle SW updates */
workbox.core.clientsClaim();

/* Activate new SW (user triggered) */
self.addEventListener('message', (event) => {
    if (event.data.action === 'skipWaiting') self.skipWaiting();
});

/* Cache files from _precacheManifest (generated by InjectManifest webpack plugin) */
self.__precacheManifest = [].concat(self.__precacheManifest || []);

self.addEventListener('activate', (event) => {event.waitUntil(clients.claim());});

/* Handle ranged quests of mp3 files */
// https://github.com/GoogleChrome/workbox/issues/1644
// https://developers.google.com/web/tools/workbox/guides/advanced-recipes#cached-av
workbox.routing.registerRoute(
  ({url}) => url.pathname.endsWith('.mp3'),
  new workbox.strategies.CacheFirst({
    cacheName: workbox.core.cacheNames.precache,
    plugins: [     
        new workbox.cacheableResponse.Plugin({ statuses: [200] }),
        new workbox.rangeRequests.Plugin(),
      ],
  })
);

/* Special fetch requests */
self.addEventListener('fetch', function(event) {
    const {
        request,
        request: {url, method},
  } = event;
  /* Game progress */
  if (url.match(GAME_DATA_ENDPOINT)) {
    if (method === 'POST') {
      /* Write data to cache */
      request.json().then(body => {
        caches.open(GAME_DATA_ENDPOINT).then(function(cache) {
          cache.put(GAME_DATA_ENDPOINT, new Response(JSON.stringify(body)));
        });
      }); 
      return new Response('{}');
    } else {
      /* Read data from cache */
      event.respondWith(
        caches.open(GAME_DATA_ENDPOINT).then(function(cache) {
          return cache.match(GAME_DATA_ENDPOINT).then(function (response) {
            return response || new Response('{}');;
          }) || new Response('{}');
          })
      );
    }
  }

  /* Cookie consent */ 
  if (url.match(COOKIE_CONSENT_ENDPOINT)) {
    if (method === 'POST') {
      /* Write data to cookie */
      request.json().then(body => {
        caches.open(COOKIE_CONSENT_ENDPOINT).then(function(cache) {
          cache.put(COOKIE_CONSENT_ENDPOINT, new Response(JSON.stringify(body)));
        });
      }); 
      return new Response('{}');
    } else {
      /* Read data from cookie */
      event.respondWith(
        caches.open(COOKIE_CONSENT_ENDPOINT).then(function(cache) {
          return cache.match(COOKIE_CONSENT_ENDPOINT).then(function (response) {
            return response || new Response('{}');;
          }) || new Response('{}');
        })
      );
    }
  }
});

/* All other requests */
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);

最佳答案

我想到了!

我必须在我的 registerRoute 中将 matchOptions 添加到 CacheFirst 策略中:

workbox.routing.registerRoute(
  ({url}) => url.pathname.endsWith('.mp3'),
  new workbox.strategies.CacheFirst({
    cacheName: workbox.core.cacheNames.precache,
    plugins: [     
        new workbox.cacheableResponse.Plugin({ statuses: [200] }),
        new workbox.rangeRequests.Plugin(),
      ],
    matchOptions: {
      ignoreSearch: true,
      ignoreVary: true
    }
  })
);

它可能与使用 Firebase 进行托管有关,但我不确定。

关于caching - 具有范围请求插件 : cannot fetch mp3 files when offline 的服务 worker ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62022640/

相关文章:

javascript - registration.showNotification 不是函数

caching - L1、L2 和 L3 缓存如何与多个并发运行的进程配合使用?

android - 清除android中的蓝牙名称缓存

Java .dat 文件到 Python pickle

audio - FFmpeg 音频转换

android - 为什么 tinyALSA 优于 libasound?

ios - kPFCachePolicyCacheThenNetwork 缓存未命中

更改 C 中缓冲区的播放速率?

service-worker - Service Worker 应该在 list 中注册还是通过脚本注册?

karma-runner - 在 Karma 测试中加载和使用 Service Worker