我正在使用服务工作者来缓存Web应用程序的JS和CSS文件。 我主要使用Google Chrome示例中的代码,我添加的唯一内容是在“新内容或更新内容可用”时刷新窗口的通知和倒计时。
然而,这种情况经常发生,我不明白为什么。 肯定没有对服务器上的文件进行任何更改,但有时我仍会看到通知和窗口重新加载。
我预计只有当服务工作者管理的任何文件实际发生变化时才会发生这种情况(它们都是通过Webpack进行哈希处理,并且两者之间绝对没有变化)。
这是我使用的代码,内联于index.html
:
/* eslint-env browser */
'use strict';
function reloadApp(delay) {
var t = delay || 0;
var message = 'New or updated content is available. Reloading app in {s} seconds';
var getMessage = function() { return message.replace('{s}', t) }
var div = document.createElement('div');
div.id = 'update-notification';
div.innerHTML = getMessage();
document.body.appendChild(div);
var intervalID = setInterval(function() {
t = t - 1;
if (t <= 0) {
clearInterval(intervalID);
window.location.reload();
}
else {
div.innerHTML = getMessage();
}
}, 1000);
}
if ('serviceWorker' in navigator && window.location.protocol === 'https:') {
navigator.serviceWorker.register('/service-worker.js').then(function(reg) {
console.info('serviceWorker registered');
reg.onupdatefound = function() {
var installingWorker = reg.installing;
installingWorker.onstatechange = function() {
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
reloadApp(5);
} else {
console.log('Content is now available offline!');
}
break;
case 'redundant':
console.error('The installing service worker became redundant.');
break;
}
};
};
}).catch(function(e) {
console.error('Error during service worker registration:', e);
});
}
这是我所做的改变:
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and the fresh content will
// have been added to the cache.
// It's the perfect time to display a "New content is available; please refresh."
// message in the page's interface.
console.log('New or updated content is available.');
} else {
成为:
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
reloadApp(5);
服务工作者本身是通过sw-precache-webpack-plugin
生成的,散列文件如下所示:
var precacheConfig = [["cms.CrudFactory.144344a2.js","6a65526f764f3caa4b8c6e0b84c1b31b"],["cms.routes.c20796b4.js","f8018476ceffa8b8f6ec00b297a6492d"],["common.cms-main.0f2db9ff.js","92017e838aff992e9f47f721cb07b6f0"],["common.licensing-main.8000b17d.js","0d43abd063567d5edaccdcf9c0e4c362"],["common.mediaplayer-main.314be5d2.js","2061501465a56e82d968d7998b9ac364"],["common.ordering-main.783e8605.js","0531c4a90a0fa9ea63fbe1f82e86f8c6"],["common.shared-main.0224b0ea.js","956ae4d2ddbddb09fb51804c09c83b22"],["common.stores-main.98246b60.js","cbdc46bc3abeac89f37e8f64b1737a22"],["component.App.284fec19.js","07f1923f1a0098bf9eba28fc7b307c18"],["component.AppToolbar.00e371de.js","9b542d4a85bdeece9d36ee4e389f6206"],["component.DevToolbar.652bf856.js","1744126e32774a93796146ac878ddd8e"],["component.Grid.4b964e52.js","755819ca2c7f911805e372401d638351"],["component.MediaPlayer.54db6e85.js","d0d8ae269665e810d1b997b473005f76"],["component.Search.05476f89.js","0cae8928aff533a6726dfaeb0661456a"],["data.country-list.d54f29a7.js","e27746418e02f75593a93b958a60807e"],["dev.sendSlackMessage.da8e22f4.js","ccb10829f18a727b79a5e8631bc4b2a2"],["index.html","02ff43eabc33c600e98785cffe7597d9"],["lib.gemini-scrollbar.df2fbf63.js","3941036bacb4a1432d22151ea7da073b"],["lib.isotope-horizontal.1604d974.js","6ac56d4296468c4428b5b5301a65938a"],["lib.isotope-packery.fabb73c3.js","808061641596e4b0ea2158b42d65915a"],["lib.react-color.265a6de0.js","f23f63d7e6934e381ffdc0405ecb449a"],["lib.react-date-picker.0a81fec3.js","778d1626645e439ad01e182ee589971a"],["lib.react-select.c768cf77.js","c8782991a161790ef2c9a2c7677da313"],["main.43e29bc6.js","fe6a6277acaa2a369ef235961be7bbcf"],["route.admin.CleanupPage.8b4bbf8e.js","8ab20412329e1ba4adc327713135be97"],["route.app.CmsPage.8a4303fb.js","0bf1506869db24bb9789c8a46449c8ad"],["route.app.CmsPageWrapper.accdebcc.js","c91e77aa8b518e1878761269deac22b6"],["route.app.ContactPage.75693d32.js","a530b00a5230a44897c2bf0aa9f402a8"],["route.app.PasswordResetExpiredDialog.65431bae.js","b5eef791dbd68edd4769bd6da022a857"],["route.app.SeriesDetailsPage.11a6989b.js","c52178b57767ae1bf94a9594cb32718e"],["route.cms.MetadataFormsPage.636188d2.js","e1e592b7e3dd82af774ac215524465c0"],["route.cms.PermissionsListPage.0e1e3075.js","9a3cc340a64238a1ab3ba1c0d483b7bd"],["route.cms.PermissionsPage.78a69f60.js","4b18e646715d6268e7aba3932f4e04a9"],["route.cms.SysconfigPage.f699b871.js","79bd1275213478f2ff1970e0b7341c49"],["styles.43e29bc620615f854714.css","b2e9e55e9ee2def2ae577ee1aaebda8f"],["styles.e0c12bb1c77e645e92d3.css","626778177949d72221e83b601c6c2c0f"],["translations.en.83fced0e.js","7e5509c23b5aafc1744a28a85c2950bb"],["translations.nl.4ae0b3bb.js","515ec7be7352a0c61e4aba99f0014a39"],["vendor.e0c12bb1.js","36ce9e0a59c7b4577b2ac4a637cb4238"]];
var cacheName = 'sw-precache-v3-nisv-client-' + (self.registration ? self.registration.scope : '');
问题:
case 'installed': if (navigator.serviceWorker.controller) {
表示New or updated content is available
的假设是否正确? 答案 0 :(得分:2)
服务人员有一个life cycle:
- registered
- installing
- installed
- waiting
- activated
- redundant
注册服务工作者时,它是从服务器获取的,disk
缓存中的生命周期取决于Web服务器发送的cache-control
响应头。
如果可能,最佳做法是cache-control : no-store must-revalidate
和max-age : 0
。
如果您忘记了,服务工作人员通常会在注册24小时后被视为stale
,并且refetched
和磁盘缓存已更新。
您可以通过在服务工作者上发布cache
版本或更改服务工作者代码来进行手动升级。即使byte
更改也会使浏览器view
成为新服务工作者,并安装新的服务工作者。
然而,这并不意味着旧服务工作者被丢弃。任何用户关闭所有标签/ 导航都必须远离您的网站,浏览器必须丢弃旧服务工作者,并且< strong>激活新的。
您可以通过self.skipWaiting
install handler
绕过此行为
那就是说,
开发时,您可以选择打开浏览器(铬)
在开发面板中,导航到application
标签,然后选中
update on reload
这样做,立即丢弃旧服务工作者,无论您的服务工作者代码是否有变化。
关于你的问题:
- 假设案例“已安装”是否正确:if(navigator.serviceWorker.controller){表示新内容或更新内容可用?
NO。这意味着,安装了新服务工作人员,例如sw-v1,并且当前waiting
已激活。
- 为什么“新的或更新的内容”案例经常发生?
你说,你正在使用sw-precache
。既然,我自己没有使用它,我必须补充一个反问题
service-worker
中的代码更改或缓存突发?如果是这样,那么,任何新版本的服务工作者在更改时都必须waiting
而不是activating
。
等待阶段skipping
的可能原因是,
self.skipWaiting
事件中有install
。注意以上情况属实,仅限
在这种情况下,您可能需要考虑注释掉self.skipWaiting
语句。或者,也许你可以配置你的插件,不要跳过更新 - 这对你的内容很重要,你需要接听电话
代替您的资产已更改和/或触发更新这一事实,
其他(最可能的)原因必须是,
您在update on reload
- &gt;下检查了application
框您的开发控制台上的service workers
标签。
取消选中该框,如果选中,则清除所有缓存,取消注册所有工作人员。之后,打开一个新选项卡并继续测试该行为。