为theGuardian.com构建脱机页面

2020-07-26 02:09:52

你在去上班的火车上,打开手机上的卫报应用程序。一条隧道包围着你,但这款应用程序的工作方式仍然与往常非常相似-尽管你缺乏互联网连接,但你仍然可以获得完整的体验,只有显示的内容会变得陈旧。但是,如果您尝试对网站执行相同的操作,它将完全不会加载:

Chrome的隐藏游戏减轻了离线的痛苦(在桌面上按空格键,在移动设备上轻拍恐龙)。但我们可以做得更好。

服务人员允许网站作者拦截对其网站的所有网络请求,这意味着我们可以提供丰富的离线体验,就像本地应用程序一样。在“卫报”上,我们最近发布了我们自己的定制离线体验。当用户离线时,他们会看到一个卫报品牌的页面,上面有一条简单的离线消息,还有一个纵横字谜供他们在等待连接时玩。这篇博客文章是关于我们是如何建造它的,但首先,这里是你可以如何亲身体验它的方法。

您必须运行支持Service Worker和Fetch API的浏览器。在撰写本文时,只有Chrome(移动端和台式机)支持这两个API,但是Firefox很快就会支持这两个API(目前是夜间版本),除了Safari之外,所有的浏览器都表现出了热情。此外,服务人员只能注册通过HTTPS提供服务的网站,theGuardian.com已经开始转向HTTPS。因此,我们只能为网站的HTTPS部分提供离线体验。目前,我们选择了开发者博客作为我们的试验场。所以,如果你在我们网站的开发者博客上读到这篇文章,你就很幸运了。

一旦您在支持的浏览器中访问了我们的开发人员博客上的页面,您就一切都准备好了。断开您的设备与互联网的连接并刷新。如果您无法亲自试用,请看此演示视频。

我们可以使用一些简单的JavaScript命令浏览器在用户到达页面后立即注册我们的服务工作者。目前对服务工作者的支持很少,因此我们需要使用功能检测来避免任何错误。

作为服务人员安装活动的一部分,我们可以使用新的缓存API来缓存我们网站的各种移动部分,如HTML、CSS和JavaScript:

Var staticCacheName=';static';var version=1;function updateCache(){1返回caches.open(staticCacheName+version)),然后(function(Cache){1)返回cache.addAll([])';/Offline-page.html';,#39;/sets/css/main.。/Assets/js/main.js';{#39;{{#};self.addEventListener(';install';,function(Event){www.event.waitUntil(updateCache());});

安装完成后,服务人员可以监听和控制FETCH事件,让我们完全控制网站将来产生的所有网络请求。

为了让您对我们这里的灵活性有一些了解,我们可以通过编程构造我们自己的响应:

Self.addEventListener(';FETCH';,Function(Event){var Response=new Response(';<;h1>;Hello,World!<;/h1>;&39;,{Headers:{';Content-Type';:';text/html';}});#event.respondWith(Response);});

或者,如果我们可以找到给定请求的匹配项,我们可以使用缓存中的内容进行响应,回退到网络:

Self.addEventListener(';FETCH';,Function(Event){Eventevent.respondWith(Fetch.caches.Match(event.request)和Event.Request);Then(Function(Response){Fetch(event.request);Function(Event.request);Function(Event.Request}));});

首先,服务人员在安装时缓存离线页面所需的HTML和资源。此缓存中包括我们为纵横字谜页面开发的Reaction应用程序。此后,我们拦截对theGuardian.com上的网页的所有网络请求,包括对这些页面上的子资源的请求。处理这些请求的逻辑大致如下:

如果我们检测到传入的请求是指向某个HTML页面的导航,我们总是希望提供最新的内容,因此我们尝试通过网络向服务器发出请求。

如果网络请求抛出错误(即,由于用户脱机而失败),我们将捕获该错误并使用脱机页面的缓存HTML进行响应。

否则,如果我们检测到请求不是HTML,我们将在缓存中查找该请求。

生成的代码使用新的缓存API(作为Service Worker API的一部分)和FETCH(用于发出网络请求),如下所示:

Var doRequestAcceptHtml=function(Request){};return request.headers.get(';Accept';);.plit(';,';);.Some(function(Type){return type=';text/html';;});};self.addEventListener(';FETCH';,Function(Event){0。**if(doRequestAcceptHtml(Request)){Do RequestAcceptHtml(';/Offline-page.html';;*FETCH(Request)*FETCH(Request)*.catch(function(){*caches.Match(';/Offline-page.html';);*})*);**}否则{//默认取回行为将首先为所有其他请求提供缓存//缓存,以获取事件.respondWith()、caches.Match(Request)、(Request),然后(function(Response){、返回响应||Fetch(Request);、())、()、();}});

我们有充分的理由对这些新的浏览器技术感到兴奋,因为它们可以用来为网站提供我们今天在本地应用程序中拥有的丰富的离线体验。将来,当theGuardian.com完成向HTTPS的迁移后,离线页面的重要性将会增加,我们可以对离线体验做进一步的改进。想象一下,在你没有互联网的通勤路上打开theGuardian.com去工作,找到为你个性化的内容,并在你访问之前由浏览器下载和缓存。安装过程中没有摩擦--与需要用户拥有应用商店帐户才能安装的本地应用不同,在网络上只需访问有问题的网站即可。服务人员还可以帮助缩短网站加载时间,因为可以像在本地应用程序中一样可靠地缓存网站的外壳。

如果你有兴趣了解更多关于服务工作者的知识和可能发生的事情,Chrome的开发者倡导者Matt Gaant已经写了一篇关于服务工作者的入门文章,对此进行了更详细的介绍。