12

I'm using Lighthouse to audit my webapp. I'm working through the failures, but I'm stuck on this one:

Failures: Manifest start_url is not cached by a Service Worker.

In my manifest.json I have

"start_url": "index.html",

In my worker.js I am caching the following:

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

Which lines up with what I see in the Application tab in Chrome Dev tools:

enter image description here

So... why is it telling me start_url is not cached?


Here is my full worker.js file:

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);
    })
  );
});
  • Have you updated the name of your cache? If not, the servieworker is not detecting the changes and is using the previous version. You should also check the `start_url` in your manifest I see it points to "index.html" not "/index.html". – Jorge Cuevas Jul 26 '17 at 20:09
  • I had tried the `start_url` with and without the preceding slash. I have added it back. I also renamed the cache to `my-site-cache-v1.1` and now I see both in the Cache Storage area, both look identical. I'm still receiving the error in Lighthouse. –  Jul 28 '17 at 19:21

2 Answers2

8

Let's look at Lighthouse's 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');
  }

}

We can notice, that it's not checking your cache, but response of the entry point. The reason for that must be that your service worker is not sending proper Response on fetch.

You'll know that it's working, if in DevTools, in your first request, there'll be (from ServiceWorker) in size column: enter image description here

There're two problems with the code you've provided:

First one is that you're messing service worker code with service worker registration code. Service worker registration code should be the code executed on your webpage.

That code should be included on your page:

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);
    });
  });
}

and the rest of what you've pasted should be your worker.js code. However service worker get installed, because you've files in cache, so I suspect you just pasted this incorrectly.

The second (real) problem is that service worker is not returning this cached files. As I've proved earlier, that error from lighthouse means that service worker is not returning start_url entry file.

The most basic code to achieve that is:

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

Service worker is event-driven, so when your page wants to get some resource, service worker reacts, and serves the one from cache. In real world, you really don't want to use it like that, because you need some kind of fallback. I strongly recommend reading section Serving files from the cache here

Edit: I've created pull request in Lighthouse source code to clarify that error message

Karol Klepacki
  • 2,070
  • 1
  • 18
  • 30
  • I'm not following you 100%. In my Network tab of DevTools I do have an entry for worker.js with (from disk cache) in the size column. Is this what you mean? –  Jul 28 '17 at 19:17
  • 1
    Success! The error is resolved and I understand caching and the service worker a bit better now. Thanks. –  Aug 01 '17 at 16:11
  • Mine still says "Manifest start_url is not cached by a Service Worker". OP, were there any tricks other than those posted above? Its driving me mental. – Jimbo Sep 08 '17 at 10:17
  • In reference to the comment above. Upon visiting the page in Android Chrome, I get an install prompt which means the error that Lighthouse is reporting is false! (or something) – Jimbo Sep 08 '17 at 11:05
  • What's the change should be done on the service worker from Create React app to achieve this? –  Apr 21 '20 at 03:40
1

It seems to be that Chrome lighthouse (chrome v62) performs a generic fetch(). See discussion on https://github.com/GoogleChrome/lighthouse/issues/2688#issuecomment-315394447

In my case, an offline.html is served after an "if (event.request.mode === 'navigate'){". Due to the use of lighthouse´s generic fetch(), lighthouse will not get served this offline.html, and shows the "Manifest start_url is not cached by a Service Worker" error.

I solved this problem by replacing:

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

with

if (event.request.method === 'GET' ){
chris
  • 11
  • 3