我正在使用服务工作者为我的网站创建一个离线页面。
目前我正在将offline.html
保存到缓存中,以便浏览器可以在没有互联网连接的情况下显示此文件。
在我的服务工作者的fetch
事件中,我尝试加载index.html
,如果失败(没有互联网连接),我从缓存中加载offline.html
。
但是,每当我在开发人员工具中检查离线模式并刷新页面时index.html
仍会显示...
请求没有失败,看起来index.html
正在被缓存,即使我没有指定它。
以下是index.html
的HTML:
<!DOCTYPE html>
<html>
<head>
<title>Service Workers - Test</title>
</head>
<body>
<h1> Online page! </h1>
<h3> You are connected to the internet. </h3>
</body>
<script>
if ('serviceWorker' in navigator)
{
navigator.serviceWorker.register('service-worker.js');
}
</script>
</html>
以下是offline.html
的HTML:
<!DOCTYPE html>
<html>
<head>
<title>You are Offline - Service Workers - Test</title>
</head>
<body>
<h1> Welcome to the Offline Page!</h1>
<h2> You are not connected to the internet but you can still do certain things offline. </h2>
</body>
</html>
以下是service-worker.js
的javascript:
const PRECACHE = "version1"
const CACHED = ["offline.html"];
// Caches "offline.html" incase there is no internet
self.addEventListener('install', event => {
console.log("[Service Worker] Installed");
caches.delete(PRECACHE)
event.waitUntil (
caches.open(PRECACHE)
.then(cache => cache.addAll(CACHED))
.then( _ => self.skipWaiting())
);
});
// Clears any caches that do not match this version
self.addEventListener("activate", event => {
event.waitUntil (
caches.keys()
.then(keys => {
return Promise.all (
keys.filter(key => {
return !key.startsWith(PRECACHE);
})
.map(key => {
return caches.delete(key);
})
);
})
.then(() => {
console.log('[Service Worker] Cleared Old Cache');
})
);
});
this.addEventListener('fetch', function(event) {
if (event.request.method !== 'GET') return;
console.log("[Service Worker] Handling Request ");
// If the request to `index.html` works it shows it, but if it fails it shows the cached version of `offline.html`
// This isn't working because `fetch` doesn't fail when there is no internet for some reason...
event.respondWith (
fetch(event.request)
.then(response => {
console.log("[Service Worker] Served from NETWORK");
return response;
}, () => {
console.log("[Service Worker] Served from CACHE");
return catches.match(event.request.url + OFFLINE_URL);
})
);
});
我正在使用python的简单http服务器运行服务器,如下所示:
python -m SimpleHTTPServer
有谁知道为什么离线页面不起作用以及如何解决这个问题?
感谢您的帮助, 大卫
修改
这些图片显示index.html
(localhost)仍然在没有互联网的情况下加载,这意味着它必须被缓存。
编辑2:
我已尝试将no-cache
添加到index.html
的抓取中,并且在我离线检查时仍然提取index.html
。
fetch(event.request, {cache: "no-cache"}) ...
答案 0 :(得分:2)
大卫,你在一行中有两个错误。
你的行
return catches.match(event.request.url + OFFLINE_URL);
应该是
return caches.match('offline.html');
它是catches
,您尚未定义OFFLINE_URL
而且您不需要事件请求网址
答案 1 :(得分:2)
答案 2 :(得分:2)
我认为从浏览器的角度来看,我们都忘记了网络请求是如何工作的。
这里的问题是,当服务工作者拦截请求时,index.html
从磁盘缓存提供。
浏览器 ===&gt; 服务工作者 ===&gt; 获取活动
在fetch事件中,我们有,
- 检查是否存在网络连接
- 如果有,请从网络获取并回复
- 否则,从缓存中获取并回复
现在,怎么做
如果有网络连接,请从网络工作中获取?
服务工作者OnFetch ===&gt; 签入磁盘缓存 ===&gt; 什么都没有?在线获取
此处提取的页面为index.html
以及cache-control
的{{1}}标头,
不指定index.html
因此,离线页面的整个问题都没有显示出来。
no-cache
标头,其中包含cache-control
的限制值 - 在服务器端或者,将获取请求中的标头添加到效果
index.html
pragma:no-cache
显然,获取和浏览器在获取GET时对请求正文有自己的保留
此外,如果您重复使用cache-control:no-cache
对象,获取提取请求并添加自定义标头,则会出现奇怪和彻头彻尾的混乱。
由于event.request
事件的Uncaught Exceptions
属性,混乱是fetch
的列表,这禁止您在无人驾驶或导航模式下将自定义标头添加到抓取中。
我们的目标是:
确定浏览器真正离线,然后提供一个说明的页面
以下是如何:
检查您是否可以使用自定义
request.mode
标头获取您的来源下的虚拟html网页test-connectivity.html
。如果可以,请继续,否则抛出离线页面
cache: no-cache
self.addEventListener( 'fetch', ( event ) => {
let headers = new Headers();
headers.append( 'cache-control', 'no-cache' );
headers.append( 'pragma', 'no-cache' );
var req = new Request( 'test-connectivity.html', {
method: 'GET',
mode: 'same-origin',
headers: headers,
redirect: 'manual' // let browser handle redirects
} );
event.respondWith( fetch( req, {
cache: 'no-store'
} )
.then( function ( response ) {
return fetch( event.request )
} )
.catch( function ( err ) {
return new Response( '<div><h2>Uh oh that did not work</h2></div>', {
headers: {
'Content-type': 'text/html'
}
} )
} ) )
} );
对象作为{cache:'no-store'}
的第二个参数,是一个不幸的 NO-OP 。只是不起作用。
只是为了未来的情况而保留它。截至今天,真的可选。
如果有效,那么您不需要为fetch
Request
对象
喝彩!
创建新请求的代码片段是慷慨借来的 @pirxpilot的回答here