【问题标题】:How to cache .mp4 files in Safari with workbox-webpack-plugin?如何使用 workbox-webpack-plugin 在 Safari 中缓存 .mp4 文件?
【发布时间】:2019-07-27 01:32:37
【问题描述】:

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

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

如何设置workbox-range-requestsworkbox-webpack-plugin

编辑:在Jeff's answer below 之后,我已将我的 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(),
      ],
   }),
);  

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

编辑:

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

【问题讨论】:

  • 你解决过这个问题吗?我有完全一样的问题。即使使用范围请求插件仍然无法使其工作。
  • @PhilippJahoda 很抱歉很晚才回复。我最终实施了我自己的解决方案作为当时的解决方法。我没有机会关注 Workbox,但距今已经快两年了,这个问题可能已经解决了。

标签: safari service-worker workbox workbox-webpack-plugin


【解决方案1】:

在 Workbox 文档的“Serve cached audio and video”配方中有针对此用例的具体指导。

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

This documentation 有在InjectManifest 模式下配置workbox-webpack-plugin 的指导。

【讨论】:

  • 谢谢,杰夫。我已经使用更新的 webpack 配置编辑了我的问题。我确实在使用GenerateSW 而不是InjectManifest 插件。但是,建议的配方仍然不起作用。当我使用干净的缓存打开页面时会呈现视频,但在重新加载时它们不再呈现。 Service Worker 的响应状态为 200 而不是 206。
  • 这意味着workbox-range-requests 没有生效。如果您不介意在此处提供更多详细信息(例如指向您的实时 Web 应用程序的链接),那么此时在 Workbox 问题跟踪器中跟进可能会更清晰。 github.com/GoogleChrome/workbox/issues
【解决方案2】:

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

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

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

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

【讨论】:

【解决方案3】:

虽然文档说将 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');
  });
}

【讨论】:

    猜你喜欢
    • 2021-03-01
    • 2019-08-30
    • 2023-03-11
    • 1970-01-01
    • 2020-08-14
    • 2021-03-22
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多