Я делаю свои первые шаги с PWA и пытаюсь заставить работать стратегию кэширования на iOS устройствах.
Мой PWA запущен и получает полные оценки на Chrome Devtools Аудит.
Я пытаюсь реализовать стратегию кэширования и затем сети. Кроме того, всякий раз, когда активируется новый сервисный работник, я хочу обновить sh кэш и получить обновленные файлы из сети.
Все отлично работает на настольном компьютере Chrome, но на устройствах iOS это просто отказывается очистить кеш и продолжает обслуживать устаревшие файлы даже после активации нового работника сервиса. Например, очистка кэша Safari вручную (!) Приведет к получению обновленной версии файла css.
Я даже пытался реализовать всплывающее уведомление, чтобы пользователь знал, что есть новая версия приложение, содержащее ссылку на sh сервисного работника, но опять же - оно хорошо работает на Chrome, но не обслуживает новые файлы на iOS - хотя оно показывает уведомление о новой версии всякий раз, когда служба Рабочий меняется, и нажав его перезагрузит страницу. Итак, я знаю, что сервисный работник обновляется на устройстве iOS, но он все еще обслуживает старые файлы.
Так как заставить устройства iOS обновить sh кэш и получить новый файлы?
Это код js, который регистрирует работника службы:
let newWorker; // Will hold the instance of the new sw so we can communicate with it
if ('serviceWorker' in navigator) {
// Register the service worker
navigator.serviceWorker.register(base_url + 'sw-test.js', { scope: base_url + 'test/' }).then(reg => {
reg.addEventListener('updatefound', () => { // An updated service worker has appeared in reg.installing!
newWorker = reg.installing;
newWorker.addEventListener('statechange', () => { // Has service worker state changed?
switch (newWorker.state) {
case 'installed': // There is a new service worker available, show the notification
if (navigator.serviceWorker.controller) {
$("#new_version_notification").removeClass("hidden_div");
$("#new_version_notification").addClass("show");
}
break;
}
});
});
});
}
// The click event on the notification
document.getElementById('reload').addEventListener('click', function(){
console.log("clicked");
newWorker.postMessage({ action: 'skipWaiting' });
return false;
});
let refreshing;
// The event listener that is fired when the service worker updates
// Here we reload the page
navigator.serviceWorker.addEventListener('controllerchange', function () {
if (refreshing) return;
window.location.reload();
refreshing = true;
});
А это мой код работника службы:
var CACHE_STATIC_NAME = 'static-v4';
var STATIC_FILES = [
'../resources/fonts/fontawesome-pro/css/all.css',
'../resources/css/mystyle.css',
'https://code.jquery.com/jquery-3.4.1.min.js',
'https://code.jquery.com/ui/1.12.1/jquery-ui.min.js'
];
//Cache Static Files:
self.addEventListener('install', function(event) {
console.log('[Service Worker] Installing Service Worker ...', event);
event.waitUntil(
caches.open(CACHE_STATIC_NAME)
.then(function(cache) {
console.log('[Service Worker] Precaching App Shell');
cache.addAll(STATIC_FILES);
})
.catch(function(err){
console.log('****** error: ', err);
})
);
});
//Serve files from the chache (if found) or from the Network (if not)
self.addEventListener('fetch',function(event){
event.respondWith(
caches.match(event.request).then(function(response){ // if it finds a match to the request in any of the caches the promise is truthy
if (response) return response; // if it's truthy return what you found in the cache
return fetch(event.request); // else return a regular fetch request
})
);
});
self.addEventListener('message', function (event) {
if (event.data.action === 'skipWaiting') {
self.skipWaiting();
}
});
// Delete old cache: ('activate' is launched when the service worker has a new version, and after the user has closed all windows)
self.addEventListener('activate', function(event) {
console.log('[Service Worker] Activating Service Worker ....', event);
event.waitUntil(
caches.keys() // caches.keys returns a Promise that resolves to an array of Cache keys.
.then(function(keyList) {
return Promise.all(keyList.map(function(key) { // Promise.all returns a single Promise that resolves when all of the promises in the iterable argument have resolved
if (key !== CACHE_STATIC_NAME && key !== CACHE_DYNAMIC_NAME) {
console.log('[Service Worker] Removing old cache.', key);
return caches.delete(key);
}
}));
})
);
return self.clients.claim();
});