【问题标题】:Manifest start_url is not cached by a Service Worker清单 start_url 没有被 Service Worker 缓存
【发布时间】:2018-01-01 23:04:12
【问题描述】:

我正在使用 Lighthouse 来审核我的 web 应用程序。我正在克服失败,但我坚持这一点:

失败:清单 start_url 没有被 Service Worker 缓存。

在我的manifest.json 我有

"start_url": "index.html",

在我的worker.js 中,我正在缓存以下内容:

let CACHE_NAME = 'my-site-cache-v1';
let urlsToCache = [
    '/',
    '/scripts/app.js',
    '/index.html'
];

这与我在 Chrome 开发工具的“应用程序”选项卡中看到的一致:

那么...为什么它告诉我start_url 没有被缓存?


这是我完整的worker.js 文件:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/worker.js').then(function(registration) {
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }, function(err) {
      console.log('ServiceWorker registration failed: ', err);
    });
  });
}

let CACHE_NAME = 'my-site-cache-v1.1';
let urlsToCache = [
  '/',
  '/scripts/app.js',
  '/index.html'
];

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(CACHE_NAME)
    .then(function(cache) {
      console.log('Opened cache');
      return cache.addAll(urlsToCache);
    })
  );
});

【问题讨论】:

  • 您是否更新了缓存的名称?如果没有,servieworker 没有检测到更改并且正在使用以前的版本。您还应该检查清单中的start_url 我看到它指向“index.html”而不是“/index.html”。
  • 我试过start_url 有和没有前面的斜线。我已经把它加回来了。我还将缓存重命名为my-site-cache-v1.1,现在我在缓存存储区域中看到两者,两者看起来相同。我仍然在 Lighthouse 中收到错误消息。

标签: service-worker progressive-web-apps manifest.json lighthouse


【解决方案1】:

Chrome 灯塔(chrome v62)似乎执行了一个通用的fetch()。参见https://github.com/GoogleChrome/lighthouse/issues/2688#issuecomment-315394447的讨论

就我而言,offline.html 在“if (event.request.mode === 'navigate'){”之后提供。 由于使用了 lighthouse 的通用 fetch(),因此 lighthouse 将不会得到这个 offline.html 的服务,并显示“Manifest start_url is not cached by a Service Worker”错误。

我通过替换解决了这个问题:

if (event.request.mode === 'navigate'){

if (event.request.method === 'GET' ){

【讨论】:

    【解决方案2】:

    我们来看看灯塔的source code

    static assessOfflineStartUrl(artifacts, result) {
      const hasOfflineStartUrl = artifacts.StartUrl.statusCode === 200;
    
      if (!hasOfflineStartUrl) {
        result.failures.push('Manifest start_url is not cached by a service worker');
      }
    
    }
    

    我们可以注意到,它不是检查您的缓存,而是入口点的响应。其原因一定是您的服务人员没有在获取时发送正确的响应。

    你会知道它正在工作,如果在 DevTools 中,在你的第一个请求中,大小列中会有(来自 ServiceWorker):

    您提供的代码有两个问题:

    第一个是您将 service worker 代码与 service worker 注册 代码搞混了。 Service Worker 注册码应该是你网页上执行的代码。

    该代码应包含在您的页面中:

    if ('serviceWorker' in navigator) {
      window.addEventListener('load', function() {
        navigator.serviceWorker.register('/worker.js').then(function(registration) {
          console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }, function(err) {
          console.log('ServiceWorker registration failed: ', err);
        });
      });
    }
    

    您粘贴的其余内容应该是您的 worker.js 代码。但是安装了服务工作者,因为您在缓存中有文件,所以我怀疑您只是错误地粘贴了这个。

    第二个(真正的)问题是 service worker 没有返回这个缓存文件。正如我之前所证明的,来自灯塔的错误意味着服务工作者没有返回start_url 入口文件。

    实现这一点的最基本代码是:

    self.addEventListener('fetch', function(event) {
      event.respondWith(caches.match(event.request));
    });
    

    Service Worker 是事件驱动的,因此当您的页面想要获取一些资源时,Service Worker 会做出反应,并从缓存中提供资源。在现实世界中,你真的不想那样使用它,因为你需要某种回退。我强烈推荐阅读部分Serving files from the cache here

    编辑:我在 Lighthouse 源代码中创建了 pull request 以澄清该错误消息

    【讨论】:

    • 我没有百分百关注你。在我的 DevTools 的 Network 选项卡中,我确实在 size 列中有一个 worker.js 条目(来自磁盘缓存)。这是你的意思吗?
    • 成功!错误已解决,我现在对缓存和 service worker 有了更好的理解。谢谢。
    • 我的仍然说“Manifest start_url 没有被 Service Worker 缓存”。 OP,除了上面贴的还有什么技巧吗?它让我精神抖擞。
    • 参考上面的评论。在 Android Chrome 中访问该页面时,我收到一个安装提示,这意味着 Lighthouse 报告的错误是错误的! (或什么)
    • 应该对 Create React 应用中的服务工作人员进行哪些更改以实现此目的?
    猜你喜欢
    • 2017-10-24
    • 2018-03-28
    • 1970-01-01
    • 2018-06-17
    • 1970-01-01
    • 2016-10-28
    • 2016-09-14
    • 2017-06-22
    • 1970-01-01
    相关资源
    最近更新 更多