Url-адрес запуска манифеста не кэшируется работником службы

Я использую Lighthouse для аудита моего webapp. Я работаю через неудачи, но я застрял на этом:

Failures: Manifest start_url не кэшируется работником службы.

в своем manifest.json Я

"start_url": "index.html",

в своем worker.js Я кэширую следующее:

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

который соответствует тому, что я вижу на вкладке Приложения В Chrome Dev tools:

enter image description here

так... почему он говорит мне start_url не кэшируется?


вот мой полный :

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

2 ответов


давайте посмотрим на Маяка исходный код

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) в столбце размера: enter image description here

есть две проблемы с код, который вы предоставили:

во-первых, что вы messing работник сервиса код Регистрация работника службы код. Регистрационный код работника службы должен быть кодом, выполняемым на вашей веб-странице.

этот код должен быть включен на странице:

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

и остальная часть того, что вы вставили, должна быть вашим работником.код js. Однако service worker устанавливается, потому что у вас есть файлы в кэше, поэтому я подозреваю, что вы просто вставили это неправильно.

вторая (реальная) проблема заключается в том, что service worker не возвращает эти кэшированные файлы. Как я уже доказал ранее, эта ошибка от lighthouse означает, что сервисный работник не возвращается start_url запись в файл.

самый основной код для достижения этого:

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

Service worker управляется событиями, поэтому, когда ваша страница хочет получить какой-то ресурс, service worker реагирует и обслуживает его из кэша. В реальном мире, вы действительно не хотите использовать его вот так, потому что тебе нужен какой-то запасной вариант. Настоятельно рекомендую прочитать раздел обслуживание файлов из кэша здесь

редактировать: я создал pull-запрос в исходном коде Lighthouse, чтобы уточнить это сообщение об ошибке


похоже, что Chrome lighthouse (chrome v62) выполняет общий fetch(). См. обсуждение https://github.com/GoogleChrome/lighthouse/issues/2688#issuecomment-315394447

в моем случае, в автономном режиме.html подается после"if (event.request.mode === 'navigate'){". Благодаря использованию маяков generic fetch(), Маяк не будет обслуживаться в автономном режиме.html и показывает, что ошибка" Manifest start_url не кэшируется работником службы".

я решил эту проблему замена:

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

С

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