Кэширование ServiceWorker не стабильно - PullRequest
1 голос
/ 09 мая 2019

Хорошо, я только начинаю работать с сервисными работниками.

В моем sw.js есть следующий код:

const cacheName = "v2"

// Call Install Event
self.addEventListener('install', function (e) {
    console.log('Service Worker: Installed')

})

// Call Activate Event
self.addEventListener('activate', function (e) {
    console.log('Service Worker: Activated')

    // Remove unwanted caches
    e.waitUntil(
        caches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames.map(cache => {
                    if(cache != cacheName) {
                        console.log('Service Worker: Clearing Old Cache')
                        return caches.delete(cache)
                    }   
                })
            )
        })
    )
})


self.addEventListener('fetch', function (e) {
    console.log("Service Worker: Fetch")

    // var url = new URL(e.request.url)
    // console.log("Fetch page: " + url)

    e.respondWith(
        //fetch(e.request).catch(() => caches.match(e.request))
        fetch(e.request)
        .then(res => {
            // Make copy/clone of response
            const responseClone = res.clone()

            // Open Cache
            caches
            .open(cacheName)
            .then(cache => {
                // Add response to cache
                cache.put(e.request, responseClone)
            })
            return response
        }).catch(err => caches.match(e.request).then(res => res))
    )

})

Который я в значительной степени скопировал из видео на YouTube. Теперь мой тестовый сайт использует несколько CDN, таблиц стилей и файлов JavaScript. Некоторые внутренние, некоторые внешние. Вот список ошибок, которые я получаю в своей консоли:

5sw.js:30 Service Worker: Fetch
5The FetchEvent for "<URL>" resulted in a network error response: an object that was not a Response was passed to respondWith().
The FetchEvent for "https://labs.domain.net/styles.css" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
(anonymous) @ sw.js:35
The FetchEvent for "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
(anonymous) @ sw.js:35
The FetchEvent for "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
(anonymous) @ sw.js:35
The FetchEvent for "https://labs.domain.net/javascript.js" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
(anonymous) @ sw.js:35
The FetchEvent for "https://code.jquery.com/jquery-3.2.1.slim.js" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
(anonymous) @ sw.js:35
index.php:7 GET https://labs.domain.net/styles.css net::ERR_FAILED
index.php:9 GET https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css net::ERR_FAILED
index.php:11 GET https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js net::ERR_FAILED
index.php:45 GET https://labs.domain.net/javascript.js net::ERR_FAILED
index.php:10 GET https://code.jquery.com/jquery-3.2.1.slim.js net::ERR_FAILED

Я не понимаю. Когда я нажимаю на ссылку, которая указывает, что это не удалось, она корректно загружается в браузере, и я вижу ее содержимое. Те, которые помечены как labs.domain.net, находятся на моем сервере и размещены рядом с файлом sw.js. Они также загружаются правильно. Но по какой-то причине работник сервиса выдает все эти ошибки.

Если я нажимаю на страницы (у меня есть три, index.php, about.php и jimmeny.php) Перед каждой загрузкой страницы я получаю сообщение «Этот веб-сайт недоступен», то страница загружается через несколько секунд после этого.

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

1 Ответ

1 голос
/ 09 мая 2019

Я бы только отправил вам комментарий, но модераторы выгнали друга, так как он некоторое время не заходил сюда, что просто отняло у меня немного репутации, чтобы я не комментировал. Хватит жаловаться ...

Просто хотел сообщить, что вы должны подумать, какие ресурсы вы кэшируете с сервисным работником. Вам необходимо реализовать политику управления кэшем, которая лучше всего подходит для создаваемого вами приложения.

Кроме того, каждый раз, когда ваш сервисный работник устанавливает новую версию, это не обязательно означает, что вы запускаете с новым кешем, кеш может управляться независимо от вариантов сервисного работника. Я бы порекомендовал вам начать использовать версионный кеш и сервисный работник. Таким образом, вы сможете лучше контролировать ситуацию. Кеш определенно стабилен.

Чтобы проверить, какие ресурсы вы в настоящий момент кэшировали для Chrome, перейдите по ссылке: Инструменты разработчика (Ctrl + Shift + I) -> Приложение (вкладка) -> Кэш -> Хранилище кеша (разверните это из бокового меню), вы должны увидеть «имя вашего кеша (ов)», как только вы выберете «кеш» имя интереса "-" v2 "вы должны точно видеть, какие ресурсы вы кэшировали в тот самый момент, когда вы просматриваете его.

Кроме того, старайтесь кэшировать только те ресурсы, которые вы контролируете. Т.е. не от третьих лиц, так как могут возникнуть некоторые вопросы, требующие изучения. Помните, что если ваш сервисный работник не контролирует сторонние ресурсы, вы не можете ожидать, что он сможет их обработать. У работника службы ниже его текущего местоположения находится имя домена, в котором оно было размещено.

Если вы хотите постоянно добавлять ресурсы, которые находятся в пределах контроля вашего сервисного работника, до выпуска новой версии сервисного работника, вы можете использовать что-то вроде этого:

self.addEventListener('fetch', event => {
    if (event.request.method === 'GET') { //only bother for static resources ;)
        switch (0) {
            case event.request.url.indexOf('https://www.google-analytics.com'):
            case event.request.url.indexOf('https://www.googletagmanager.com'):
                // skip adding to cache
                // console.warn('skip adding to cache ' + event.request.method + ' ' + event.request.mode + ' ' + event.request.url);
            break;
            case event.request.url.indexOf(SERVER_URL):
                // Cache falling back to network
                // console.info('[PWA] The service worker is serving an asset. ' + event.request.method + ' ' + event.request.mode + ' ' + event.request.url);
                event.respondWith(
                    caches.open(CACHE_NAME).then((cache) => {
                        return cache.match(event.request).then((response) => {
                            return response || fetch(event.request).then((response) => {
                                if (response.status === 200) {
                                    cache.put(event.request, response.clone());
                                    return response;
                                } else if (response.type === 'opaqueredirect' || response.status === 404) {
                                    return response;
                                } else {
                                    return cache.match('offline.html');
                                }
                            }).catch(() => {
                                return cache.match('offline.html');
                            });
                        });
                    })
                );
            break;
            default:
            // console.warn('new case for cache ' + event.request.method + ' ' + event.request.mode + ' ' + event.request.url);
        }
    }
});

В этом примере вы бы кэшировали «offline.html» при установке программного обеспечения, чтобы вы могли отображать его, когда пользователь пытается получить доступ к ресурсам в автономном режиме, а ресурс ранее не кэшировался. Этот метод может быть описан как «обслуживать кеш или брать ресурсы из сети, а затем обслуживать из кеша». Вам также потребуется реализовать логику для обрезки / замены / обновления кеша статических ресурсов посредством выпуска новых вариантов сервисного работника и выполнения этой логики по мере необходимости.

ура!

...