javascript - 安装新的 serviceworker 时页面没有响应。每次小更新都会重新获取所有静态文件
问题描述
- 在安装新的 serviceworker 时,我们的页面变得无响应。我们的目标是安装新的 serviceworker,但要防止安装处理程序请求与主页请求争夺带宽的资源。
- serviceworker 安装事件需要大量时间,因为所有文件都被再次获取,即使是在很小的更新之后。serviceworker 应该只在更新后(重新)获取动态文件(参见下面代码中的 mutableRequests)。在 serviceworker 更新后应该只获取新的静态文件,而不是所有的静态文件(参见下面代码中的 immutableRequests)。
请在代码中找到以下注释,这些注释解释了我已经尝试过的事情。
// Register the serviceworker:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker
.register('/sw.js')
.then(function() { console.log("Service Worker Registered"); });
});
}
// The serviceworker:
'use strict';
// To update the version of the serviceworker:
var CACHE_NAME = 'swwo-cache-v143';
// The 'static' assets:
var immutableRequests = [
// Many assets here:
'/js/awesomplete.js',
'/js/bootstrap.min.js',
'/img/earth-from-space.jpg'
// ETC...
];
// The 'dynamic' assets:
var mutableRequests = [
// Only a few assets here:
'/index.html',
'/legal.html'
// ETC...
];
// Here the goal was to make sure that all the mutableRequests are being fetched again, and only the NEW immutableRequests:
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(CACHE_NAME).then(function(cache) {
var newImmutableRequests = [];
return Promise.all(
immutableRequests.map(function(url) {
return caches.match(url).then(function(response) {
if (response) {
return cache.put(url, response);
} else {
newImmutableRequests.push(url);
return Promise.resolve();
}
});
})
).then(function() {
return cache.addAll(newImmutableRequests.concat(mutableRequests));
});
})
);
});
self.addEventListener('fetch', event => {
var requestURL = new URL(event.request.url);
// Try the cache first:
if (requestURL.origin == location.origin && requestURL.pathname == '/') {
event.respondWith(caches.match('/index.html'));
return;
}
// Analytics exception:
else if (requestURL.host === 'www.google-analytics.com') {
event.respondWith(fetch(event.request));
}
else {
event.respondWith(
// Try the cache:
caches.match(event.request)
// Fall back to the network:
.then(response => response || fetch(event.request))
// A general fallback:
.catch(function() {
return caches.match('/offline/index.html');
})
);}
});
// Removing the old cache:
self.addEventListener('activate', function(event) {
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
if (CACHE_NAME !== cacheName) {
console.log('Deleting out of date cache:', cacheName);
return caches.delete(cacheName);
}
})
);
})
);
});
解决方案
1.
return caches.match(url).then(function(response) {
有一个错误:您应该调用 cache.match 来匹配您感兴趣的缓存。不是带有“s”的 cacheS :)
2.
如果您总是更新缓存的名称
// To update the version of the serviceworker:
var CACHE_NAME = 'swwo-cache-v143';
那么从那里将找不到以前获取和缓存的资产,对吗?
请记住:即使 SW 脚本文件中的 SINGLE BYTE 更改,浏览器也会认为 SW 脚本是新的,因此您要缓存的资产中的任何更改都会使 SW 对浏览器来说是新的。如果您不需要任何东西,则无需在任何地方保留单独的版本号。这里似乎引起了问题。如果你想拥有它,你可以将版本号放在评论中。
还有一件事要注意:如果您真的不需要软件尽快注册/更新,您可以推迟它。使用 setTimeout 将 SW 注册延迟 15 秒或其他任何时间,以便用户尽快使用该页面。这使应用程序更流畅。
推荐阅读
- python - 使用 AJAX 时的 Django 反向匹配
- vcpkg - vcpkg安装后点云库缺少头文件
- javascript - navbar.js 被componentdidmount 函数添加后没有加载到DOM 上?
- pandas - Xarray - 在时区感知时间维度上按小时到每天重新采样
- pandas - 在 YearMonth 的数据框系列中查找差距
- nginx - CentOS 显示 NGINX 页面而不是烧瓶应用程序?
- delphi - 用帕斯卡格式化分数
- forms - Flutter Form 控制器抛出“方法 'validate' 在 null 上被调用”
- python - 如何将 S3 Select 与制表符分隔的 csv 文件一起使用
- hibernate - @DynamicUpdate - 无法仅查询更改的结果