冠富商务通中文社区

 找回密码
 立即注册
查看: 9|回复: 0
打印 上一主题 下一主题
收起左侧

[建站策划] 连不上网?英国卫报的个性离线页面是这样做的

[复制链接]
跳转到指定楼层
楼主
发表于 2017-1-1 14:10:47 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
我们是如何使用 service worker 来为 theguardian.com 构建一个自定义的离线页面。

theguardian.com 的离线页面。插图:oliver Ash

你正在通往公司路上的地铁里,在手机上打开了 Guardian 应用。地铁被隧道包围着,不过这个应用可以如常运行,即使没有网络连接,你也能获得完整的功能,除了显示的内容可能有点旧。如果你尝试在网站上也这么干,可惜它完全没法加载:

安卓版 Chrome 的离线页面

Chrome 在离线页面上有个隐藏的游戏(桌面版上按空格键,手机版上点击那只恐龙),这多少能减轻一点你的烦躁。不过我们可以做得更好。
Service workers 允许网站作者拦截自己站点的所有网络请求,这也就意味着我们可以提供完善的离线体验,就像原生应用一样。在 Guardian 网站,我们最近上线了一个自定义的离线体验功能。当用户离线的时候,他们会看到一个带有 Guardian 标识的页面,上面带有一个简短的离线提示,还有一个填字游戏,他们可以在等待网络连接的时候玩玩这个找点乐子。这篇博客解释了我们是如何构建它的,不过在开始之前,你可以先自己试试看。
试试看
你需要一个支持 Service Worker 和 fetch API 的浏览器。截止到本文编写时只有 Chrome(手机版和桌面版)同时支持这两种 API(译者注:Opera 目前也支持这两者),不过 Firefox 很快就要支持了(在每日更新的版本中已经支持了),除了 Safari 之外的所有浏览器也都在跃跃欲试。此外,service worker 只能注册在使用了 HTTPS 的网站上,theguardian.com 已经开始逐步迁移到 HTTPS,所以我们只能在网站的 HTTPS 部分提供离线体验。就目前来说,我们选择了 开发者博客 作为我们用来测试的地方。所以如果你是在我们网站的 开发者博客部分阅读这篇文章的话,很走运。
当你使用支持的浏览器访问我们的 开发者博客 中的页面的时候,一切就准备妥当了。断开你的网络连接,然后刷新一下页面。如果你自己没条件尝试的话,可以看一下这段 演示视频(译者注:需翻墙)。
工作原理
通过一段简单的 Javascript,我们可以指示浏览器在用户访问页面的时候立即注册我们自己的 service worker。目前支持 service worker 的浏览器很少,所以为了避免错误,我们需要使用特性检测。
if(navigator.serviceWorker){
    navigator.serviceWorker.register('/service-worker.js');
}

Service worker 安装事件的一部分,我们可以使用 新的缓存 API 来缓存我们网站中的各种内容,比如 HTML、CSS 和 JavaScript:
varstaticCacheName='static';
varversion=1;

functionupdateCache(){
    returncaches.open(staticCacheName+version)
        .then(function(cache){
            returncache.addAll([
                '/offline-page.html',
                '/assets/css/main.css',
                '/assets/js/main.js'
            ]);
        });
};

self.addEventListener('install',function(event){
    event.waitUntil(updateCache());
});

当安装完成后,service worker 可以监听和控制 fetch 事件,让我们可以完全控制之后网站中产生的所有网络请求。
self.addEventListener('fetch',function(event){
    event.respondWith(fetch(event.request));
});

在这里我们有很灵活的空间可以发挥,比如下面这个点子,可以通过代码来生成我们自己的请求响应:
self.addEventListener('fetch',function(event){
    varresponse=newResponse('<h1>Hello, World!</h1>',
        {headers:{'Content-Type':'text/html'}});
    event.respondWith(response);
});

还有这个,如果在缓存中找到了请求相应的缓存,我们可以直接从缓存中返回它,如果没找到的话,再通过网络获取响应内容:
self.addEventListener('fetch',function(event){
    event.respondWith(
        caches.match(event.request)
            .then(function(response){
                returnresponse||fetch(event.request);
            })
    );
});

那么我们如何使用这些功能来提供离线体验呢?
首先,在 service worker 安装过程中,我们需要把离线页面需要的 HTML 和资源文件通过 service worker 缓存下来。在缓存中,我们加载了自己开发的 填字游戏React应用页面。之后,我们会拦截所有访问 theguardian.com 网络请求,包括网页、以及页面中的资源文件。处理这些请求的逻辑大致如下:

  • 当我们检测到传入请求是指向我们的 HTML 页面时,我们总是会想要提供最新的内容,所以我们会尝试把这个请求通过网络发送给服务器。

    • 当我们从服务器得到了响应,就可以直接返回这个响应。
    • 如果网络请求抛出了异常(比如因为用户掉线了),我们捕获这个异常,然后使用缓存的离线 HTML 页面作为响应内容。

  • 否则,当我们检测到请求的不是 HTML 的话,我们会从缓存中查找响应的请求内容。

    • 如果找到了缓存内容,我们可以直接返回缓存的内容。
    • 否则,我们会尝试把这个请求通过网络发送给服务器。

在代码中,我们使用了 新的缓存 API(它是 Service Worker API 的一部分)以及 fetch 功能(用于生成网络请求),如下所示:
vardoesRequestAcceptHtml=function(request){
    returnrequest.headers.get('Accept')
        .split(',')
        .some(function(type){returntype==='text/html';});
};

self.addEventListener('fetch',function(event){
    varrequest=event.request;
    if(doesRequestAcceptHtml(request)){
        // HTML pages fallback to offline page
        event.respondWith(
            fetch(request)
                .catch(function(){
                    returncaches.match('/offline-page.html');
                })
        );
    }else{
        // Default fetch behaviour
        // Cache first for all other requests
        event.respondWith(
            caches.match(request)
                .then(function(response){
                    returnresponse||fetch(request);
                })
        );
    }
});

就只需要这么多!theguardian.com 上的 所有代码都是在 GitHub 上开源 的,所以你可以去那儿查看我们的 service worker 的完整版本,或者直接从生产环境上访问 https://www.theguardian.com/service-worker.js
我们有充足的理由为这些新的浏览器技术欢呼喝彩,因为它可以用来让你的网站像今天的原生应用一样,拥有完善的离线体验。未来当 theguardian.com 完全迁移到 HTTPS 之后,离线页面的重要性会明显增加,我们可以提供更加完善的离线体验。设想一下你在上下班路上网络很差的时候访问 theguardian.com,你会看到专门为你订制的个性化内容,它们是在你之前访问网站时由浏览器缓存下来的。它在安装过程中也不会产生任何不便,你所需要的只是访问这个网站而已,不像原生应用,还需要用户有一个应用商店的账号才能安装。Service worker 同样可以帮助我们提升网站的加载速度,因为网站的框架能够被可靠地缓存下来,就像原生应用一样。
如果你对 service worker 很感兴趣,想要了解更多内容的话,开发者 Matt Gaunt(Chrome的忠实支持者)写了一篇更加详细地介绍 Service Worker的文章。
                                                                                注:相关网站建设技巧阅读请移步到建站教程频道。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|关于我们|申请友链|Archiver|手机版|拘留所|冠富商务通

GMT+8, 2025-5-19 03:18 , Processed in 0.133008 second(s), 17 queries , Wincache On.

Powered by HCMS Version 2.0

© 2008-05-14 guanfu.net.cn

快速回复 返回顶部 返回列表