4

我在https://github.com/GoogleChrome/workbox/issues/1663报告了完全相同的问题,该问题描述了仅在 Safari 中发生的问题,其中 mp4 视频在被服务人员缓存后未呈现。

我正在使用workbox-webpack-plugin,因此评论中提供的说明https://github.com/GoogleChrome/workbox/issues/1663#issuecomment-448755945不适用于我的情况。我无法workbox-range-requests在我的 webpack 配置文件中要求插件并将其传递给运行时缓存选项,因为我相信这个包仅供浏览器使用。我的工作箱配置正在预缓存 .mp4 资产,并使用网络优先策略进行运行时缓存。

我该如何workbox-range-requests设置workbox-webpack-plugin

编辑:在下面 Jeff 的回答之后,我将我的 webpack 配置调整为以下内容:

new WorkboxPlugin.InjectManifest({
   swSrc: serviceWorkerSrcPath,
   swDest: serviceWorkerBuildPath,
   importsDirectory: 'sw',
})

该构建产生以下服务工作者:

importScripts("/_build/sw/precache-manifest.8a0be820b796b153c97ba206d9753bdb.js", "https://storage.googleapis.com/workbox-cdn/releases/3.6.2/workbox-sw.js");

workbox.precaching.precacheAndRoute(self.__precacheManifest || []);

workbox.routing.registerRoute(
   /.*\.mp4/,
   new workbox.strategies.CacheFirst({
      cacheName: 'videos',
      plugins: [
         new workbox.cacheableResponse.Plugin({ statuses: [200] }),
         new workbox.rangeRequests.Plugin(),
      ],
   }),
);  

如果之前忘记提及,但我还crossOrigin="anonymous"为元素添加了属性video

编辑:

证明它在 Safari 上无法按预期工作的重现:https ://github.com/acostalima/workbox-range-requests-mp4-demo

4

3 回答 3

2

在 Workbox 文档中的“提供缓存的音频和视频”配方中有针对此用例的具体指导。

您可以继续使用workbox-webpack-plugin,但我建议在InjectManifest模式下使用它,这将使您能够控制顶级服务工作者文件。反过来,这将使遵循食谱成为可能。

本文档workbox-webpack-plugin提供有关在InjectManifest模式下进行配置的指南。

于 2019-03-05T22:07:46.590 回答
0

尽管文档说将 mp4 添加到预缓存缓存然后配置范围插件以处理预缓存 mp4 应该可以工作,但实际上并非如此。从预缓存中删除 mp4 并使用 range 插件配置您自己的视频缓存对我来说是诀窍。不要忘记将crossorigin="anonymous"标签添加到您的视频中!

这是我的做法(webpack 5,workbox 6):

// src/service-worker.js
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { cacheNames } from 'workbox-core';
import { precacheAndRoute } from 'workbox-precaching';
import { RangeRequestsPlugin } from 'workbox-range-requests';
import { registerRoute } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';

const allEntries = self.__WB_MANIFEST; // Injected by WorkboxWebpackPlugin at compile time
const videoEntries = allEntries.filter((entry) => entry.url.endsWith('.mp4'));
const restEntries = allEntries.filter((entry) => !entry.url.endsWith('.mp4'));

precacheAndRoute(restEntries);

const videoCacheName = `${cacheNames.prefix}-videos-${cacheNames.suffix}`;

self.addEventListener('install', (event) => {
  const allVideosAddedToCache = caches.open(videoCacheName).then((videoCache) => {
    const videoUrls = videoEntries.map((entry) => entry.url);
    return videoCache.addAll(videoUrls);
  });
  event.waitUntil(allVideosAddedToCache);
});

registerRoute(
  (route) => route.url.pathname.endsWith('.mp4'),
  new CacheFirst({
    cacheName: videoCacheName,
    plugins: [new CacheableResponsePlugin({ statuses: [200] }), new RangeRequestsPlugin()],
  })
);
// webpack.config.js
plugins: [
  new WorkboxWebpackPlugin.InjectManifest({
    swSrc: 'src/service-worker.js',
  }),
]
// index.tsx
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js');
  });
}
于 2022-01-05T18:12:37.017 回答
0

我在 Safari 上遇到了同样的问题,并设法通过从 precahe 列表中删除我的视频,self.__precacheManifest而不是将其添加到服务人员的安装处理程序中来解决它:

self.addEventListener('install', (event) => {

        const urls = [/* videoUrl */];
        const cacheName = 'videos';
        event.waitUntil(caches.open(cacheName).then((cache) => cache.addAll(urls)));
});

查看日志,似乎只有预缓存用于响应对视频资源的请求,而不是路由器。

于 2019-09-15T21:46:17.913 回答