javascript - ServiceWorker 缓存不稳定

标签 javascript service-worker

好的,我才刚刚开始使用 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/

相关文章:

javascript - 如何从 Webhook 运行 Gulp

javascript - 将 Angular 书面扩展迁移到 list V3

javascript - 如何增加 'chrome push notification' 可见时间?

javascript - 如何将 3 个下拉菜单合并为一个?

javascript - virtual &lt;input type ="file"> 元素 - 不可靠的 onchange 事件 - 为什么?

javascript - 按顺序调用多个函数使用ng-click,单击并将相同的变量传递给多个函数

javascript - 如何读取客户端机器的IPV4地址?

reactjs - 如何使用 create-react-app 从 Service Worker 中排除某些 url?

javascript - Service Worker 在获取 MP3 音频时抛出错误

android - Service Worker client.openWindow 从 list 中打开 start_url 而不是请求的 URL