PWA:服务工作者更新但未缓存文件
PWA: service worker updated but not cached files
我目前正在尝试从头开始构建 PWA。我在处理更新时遇到了一些麻烦。
基于this article,我编写了一个代码,当有新版本的 service worker 可用时显示一个按钮。单击该按钮时,将安装新的工作程序,并将 shell 个文件存储在缓存中。
为了测试此功能,我构建了一个仅包含 index.html
和 service-worker.js
文件的最小示例。
var cache_version = 'v2';
var cache_name = 'test-pwa-'+cache_version;
var shell_files = [
'./index.html'
];
self.addEventListener('message', evt => {
if (evt.data.action == 'skipWaiting')
self.skipWaiting();
});
self.addEventListener('install', evt => {
evt.waitUntil(caches.open(cache_name).then(cache => {
return cache.addAll(shell_files);
}));
});
self.addEventListener('activate', evt => {
evt.waitUntil(caches.keys().then(key_list => {
return Promise.all(key_list.map(key => {
if (cache_name.indexOf(key) === -1)
return caches.delete(key);
}));
}));
});
self.addEventListener('fetch', evt => {
evt.respondWith(
caches.match(evt.request).then(cache_response => {
return cache_response || fetch(evt.request).then(response => {
return caches.open(cache_name).then(cache => {
cache.put(evt.request, response.clone());
return response;
});
});
})
);
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test of PWA</title>
</head>
<body>
<h1>Hello World!</h1>
<p id="refresh" style="display: none;"><button>New update!</button></p>
<script>
if ('serviceWorker' in navigator) {
var new_worker;
var refreshing = false;
navigator.serviceWorker.addEventListener('controllerchange', () => {
if (refreshing)
return;
window.location.reload();
refreshing = true;
});
navigator.serviceWorker.register('service-worker.js').then(registration => {
registration.addEventListener('updatefound', () => {
new_worker = registration.installing;
new_worker.addEventListener('statechange', () => {
if (new_worker.state == 'installed' && navigator.serviceWorker.controller) {
var notification = document.querySelector('#refresh');
notification.querySelector('button').addEventListener('click', () => {
new_worker.postMessage({action: 'skipWaiting'});
});
notification.style.display = 'block';
}
});
});
}).catch(err => {
console.log('Something went wrong during the registration');
});
}
</script>
</body>
</html>
现在,我更改 HTML 文件,例如,在标题后添加一个新的段落元素。然后,我更改服务工作者中的 cache_version
变量。当我重新加载页面时,会显示更新按钮。当我点击它时,我可以看到(在 Firefox 工具中)旧缓存被删除,并按预期创建了一个新的缓存文件夹。但是,index.html
文件没有改变(我没有看到新段落)。
有什么想法吗?
感谢 C14L 的评论,我发现问题来自 HTTP 缓存。为了调试,我们可以从浏览器的工具中禁用缓存。对于生产,我们可以绕过 HTTP 缓存或使用 .htaccess
文件控制它。我为感兴趣的人找到了一些有用的信息here。
我目前正在尝试从头开始构建 PWA。我在处理更新时遇到了一些麻烦。
基于this article,我编写了一个代码,当有新版本的 service worker 可用时显示一个按钮。单击该按钮时,将安装新的工作程序,并将 shell 个文件存储在缓存中。
为了测试此功能,我构建了一个仅包含 index.html
和 service-worker.js
文件的最小示例。
var cache_version = 'v2';
var cache_name = 'test-pwa-'+cache_version;
var shell_files = [
'./index.html'
];
self.addEventListener('message', evt => {
if (evt.data.action == 'skipWaiting')
self.skipWaiting();
});
self.addEventListener('install', evt => {
evt.waitUntil(caches.open(cache_name).then(cache => {
return cache.addAll(shell_files);
}));
});
self.addEventListener('activate', evt => {
evt.waitUntil(caches.keys().then(key_list => {
return Promise.all(key_list.map(key => {
if (cache_name.indexOf(key) === -1)
return caches.delete(key);
}));
}));
});
self.addEventListener('fetch', evt => {
evt.respondWith(
caches.match(evt.request).then(cache_response => {
return cache_response || fetch(evt.request).then(response => {
return caches.open(cache_name).then(cache => {
cache.put(evt.request, response.clone());
return response;
});
});
})
);
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test of PWA</title>
</head>
<body>
<h1>Hello World!</h1>
<p id="refresh" style="display: none;"><button>New update!</button></p>
<script>
if ('serviceWorker' in navigator) {
var new_worker;
var refreshing = false;
navigator.serviceWorker.addEventListener('controllerchange', () => {
if (refreshing)
return;
window.location.reload();
refreshing = true;
});
navigator.serviceWorker.register('service-worker.js').then(registration => {
registration.addEventListener('updatefound', () => {
new_worker = registration.installing;
new_worker.addEventListener('statechange', () => {
if (new_worker.state == 'installed' && navigator.serviceWorker.controller) {
var notification = document.querySelector('#refresh');
notification.querySelector('button').addEventListener('click', () => {
new_worker.postMessage({action: 'skipWaiting'});
});
notification.style.display = 'block';
}
});
});
}).catch(err => {
console.log('Something went wrong during the registration');
});
}
</script>
</body>
</html>
现在,我更改 HTML 文件,例如,在标题后添加一个新的段落元素。然后,我更改服务工作者中的 cache_version
变量。当我重新加载页面时,会显示更新按钮。当我点击它时,我可以看到(在 Firefox 工具中)旧缓存被删除,并按预期创建了一个新的缓存文件夹。但是,index.html
文件没有改变(我没有看到新段落)。
有什么想法吗?
感谢 C14L 的评论,我发现问题来自 HTTP 缓存。为了调试,我们可以从浏览器的工具中禁用缓存。对于生产,我们可以绕过 HTTP 缓存或使用 .htaccess
文件控制它。我为感兴趣的人找到了一些有用的信息here。