首页 > 解决方案 > Safari service worker work incorrect with custom offline page

问题描述

I created a pwa version of the site with a custom offline page using the service worker. When navigating through pages, they are added to the cache, and when they are visited again, it is shown from the cache. When you click on a link and do not connect to the Internet and this page is not cached, an offline page is displayed.

offline page screen

There are 2 options to refresh the page:

offline page reload link

offline page

With the first option there is no problem. And with the second there is a problem in the safari. The problem occurs when:

  1. clicked on the link without an Internet connection and received an offline page
  2. The next time already with the Internet connection went on the same link and again received an offline page, although it should show an online page

Steps to reproduce the problem:

  1. go to the site with the Internet turned on
  2. turn off the Internet
  3. go to page1.html (an offline page is displayed)
  4. go back to index.html (go home link)
  5. turn on the internet
  6. go back to page1.html (an offline page is displayed, but page1.html should be displayed)
  7. go to page2.html - everything works correctly, the online page loads

Who faced such a problem? It seems that the safari remembers request-response bunch and return the same result, regardless of the connection to the Internet.

'use strict';

const CACHE_VERSION = 1;
const BASE_URL = location.origin + '/';
const OFFLINE_URL = '/offline.html';

const CURRENT_CACHES = {
  offline: 'offline-v' + CACHE_VERSION,
};

const URLS_TO_CACHE = [
  BASE_URL,
  OFFLINE_URL,
];


self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CURRENT_CACHES.offline)
      .then(cache => {
        return cache.addAll(URLS_TO_CACHE);
      })
      .then(() => {
        return self.skipWaiting()
      })
  );
});


self.addEventListener('activate', event => {
  let expectedCacheNames = Object.keys(CURRENT_CACHES).map(function (key) {
    return CURRENT_CACHES[key];
  });

  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cacheName => {
          if (expectedCacheNames.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
    .then(() => {
      return self.clients.claim()
    })
  );
});


// fetch requests
self.addEventListener('fetch', event => {
  const responsePromiseFactory = () => {
    return caches.open(CURRENT_CACHES.offline).then((cache) => {
      return cache.match(event.request).then(response => {
        if (response) {
          return response;
        }

        const fetchRequest = event.request.clone();

        return fetch(fetchRequest)
          .then(response => {
            const responseToCache = response.clone();

            if (!response || response.status !== 200 || response.type !== 'basic') {
              return response;
            }

            cache.put(event.request, responseToCache)

            return response;
          })
        })
      })
      .catch(error => {
        return caches.match(OFFLINE_URL)
      })
  };

  event.respondWith(responsePromiseFactory());
});

Tested on safari desktop v.11.1 and mobile safari ios version 11.3.1

标签: safarifetchofflineservice-workerprogressive-web-apps

解决方案


我遇到了完全相同的情况,通过在我的离线页面中添加以下标题,Safari 现在在互联网连接可用时为在线页面提供服务。

<head>
  <meta http-equiv="cache-control" content="max-age=0" />
  <meta http-equiv="expires" content="0" />
  <meta http-equiv="pragma" content="no-cache" />
</head>


推荐阅读