好的,我才刚刚开始使用 Service Workers。
我的 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 文件一起托管。他们也正确加载。但出于某种原因,Service Worker 抛出了所有这些错误。
如果我点击页面(我有三个页面,index.php、about.php 和 jimmeny.php),在加载每个页面之前,我会收到一条“无法访问此网站”的消息,然后页面会加载几秒钟在那之后。
有人可以指出我在这方面出错的正确方向吗?我的网站非常简单,我不明白为什么资源不能正确保存。
最佳答案
我只会给你发评论,但版主将一位 friend 踢出局,因为他有一段时间没有在这里登录,这对我的声誉造成了一些影响,阻止我发表评论。提示够了……
只是想让您知道,您应该考虑使用 Service Worker 缓存哪些资源。您需要实现最适合您正在构建的应用程序的缓存控制策略。
此外,每次您的 Service Worker 安装新版本并不一定意味着您从新的缓存开始,缓存可以独立于 Service Worker 变体进行管理。我建议您应该开始同时使用版本化缓存和服务 worker 。这样你就能更好地控制局面。缓存绝对稳定。
要检查您当前为 Chrome 缓存了哪些资源,请访问: 开发人员工具(Ctrl + Shift + I)-> 应用程序(选项卡)-> 缓存-> 缓存存储(从侧面菜单展开)您应该看到“缓存的名称”,一旦您选择“缓存”感兴趣的名称”-“v2”,您应该在查看它的非常精确的时刻准确地看到您缓存了哪些资源。
另外,尽量只缓存你能控制的资源。即不是来自第三方,因为可能存在一些需要调查的问题。请记住,如果您的 service worker 不控制第三方资源,您就不能指望它能够处理它们。 service worker 的作用域低于其所在域名的当前位置。
如果您想永久添加在您的 service worker 控制范围内的资源,直到发布新版本的 service worker,您可以使用这样的东西:
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);
}
}
});
在本例中,您将在安装 SW 时缓存“offline.html”,以便在用户尝试离线访问资源且该资源之前未缓存时显示它。该方法可以描述为“服务缓存或从网络获取资源,然后再从缓存服务”。您还需要通过发布新的 Service Worker 变体来实现 trim/替换/更新静态资源缓存的逻辑,并在需要时执行此逻辑。
干杯!
关于javascript - ServiceWorker 缓存不稳定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56061154/