菜单

连不上网?大不列颠及苏格兰联合王国卫报的特性离线页面是那般做的

2019年2月26日 - 金沙前端

利用Service worker完成加速/离线访问静态blog网站

2017/02/19 · JavaScript
· Service Worker

原稿出处: Yang
Bo   

近日很盛行基于Github
page和markdown的静态blog,分外适合技术的思考和习惯,针对分裂的语言都有一对完美的静态blog系统出现,如Jekyll/Ruby,Pelican/Python,Hexo/NodeJs,由于静态内容的风味十分适合做缓存来加速页面包车型客车访问,就选择Service
worker
来促成加速,结果是除了PageSpeed,CDN这么些大规模的服务器和网络加快之外,通过客户端完成了更好的拜会体验。

Service Worker入门

2015/03/26 · JavaScript
· Service Worker

原稿出处: Matt
Gaunt   译文出处:[w3ctech

金沙国际,原生App拥有Web应用一般所不有所的富离线体验,定时的沉默更新,音信通知推送等职能。而新的Serviceworkers标准让在Web App上享有这一个效应成为大概。

接纳 瑟维斯 worker 创制1个分外简单的离线页面

2016/06/07 · JavaScript
· 1 评论 · Service
Worker

本文由 伯乐在线 –
刘健超-J.c
翻译,艾凌风
校稿。未经许可,禁止转发!
英文出处:Dean
Hume。欢迎参与翻译组。

让我们想像以下处境:大家那时候在一辆通往农村的列车上,用运动装备看着一篇很棒的篇章。与此同时,当您点击“查看更加多”的链接时,高铁忽然进入了隧道,导致移动装备失去了网络,而
web 页面会展现出类似以下的始末:

金沙国际 1

那是一对一令人黯然的体会!幸运的是,web
开发者们能经过一些新特点来更始那类的用户体验。小编近年径直在折腾 ServiceWorkers,它给 web 带来的无尽恐怕性总能给本人惊喜。Service Workers
的理想特质之一是允许你检查和测试互联网请求的场地,并让您作出相应的响应。

在那篇小说里,笔者打算用此天性检查用户的当下网络连接处境,假设没连接则赶回三个最佳简单的离线页面。尽管那是3个尤其基础的案例,但它能给您带来启发,让你驾驭运营并运维该特性是何等的简练!假如您没掌握过
Service Worker,笔者建议你看看此 Github
repo,明白越多相关的新闻。

在此案例初步前,让大家先不难地看望它的办事流程:

  1. 在用户第①回访问大家的页面时,大家会设置 ServiceWorker,并向浏览器的缓存添加大家的离线 HTML 页面
  2. 然后,假诺用户打算导航到另多少个 web
    页面(同二个网站下),但此时已断网,那么大家将回到已被缓存的离线
    HTML 页面
  3. 不过,假若用户打算导航到别的2个 web
    页面,而那时互联网已一而再,则能照常浏览页面

连不上网?U.K.卫报的性格离线页面是这样做的

2015/11/20 · HTML5 · Service
Worker,
离线页面

本文由 伯乐在线 –
Erucy
翻译,weavewillg
校稿。未经许可,禁止转发!
英文出处:Oliver
Ash。欢迎参与翻译组。

大家是怎么使用 service worker 来为 theguardian.com
创设3个自定义的离线页面。

金沙国际 2

theguardian.com 的离线页面。插图:奥利弗 Ash

你正在朝着公司途中的大巴里,在堂哥大上开拓了
Guardian
应用。大巴被隧道包围着,但是那几个动用可以健康运营,固然没有互联网连接,你也能赢得完整的功用,除了出示的剧情大概有点旧。假诺你尝试在网站上也如此干,可惜它完全无法加载:

金沙国际 3

安卓版 Chrome 的离线页面

Chrome 中的那几个彩蛋,很多个人都不明了》

Chrome
在离线页面上有个暗藏的嬉戏(桌面版上按空格键,手机版上点击那只恐龙),这多少能减轻一点你的烦心。然而我们得以做得更好。

Service
workers
允许网站小编拦截本人站点的装有互连网请求,那也就意味着我们得以提供全面的离线体验,就像是原生应用相同。在
Guardian
网站,我们近来上线了一个自定义的离线体验效果。当用户离线的时候,他们会看到二个包蕴Guardian
标识的页面,上边带有贰个简便的离线提示,还有2个填字游戏,他们得以在等候网络连接的时候玩玩那些找点乐子。那篇博客解释了我们是怎么着创设它的,不过在起先在此之前,你能够先自身试试看。

加速/离线访问只需三步

JavaScript

<script> if (‘serviceWorker’ in navigator) {
navigator.serviceWorker.register(‘/sw.js’); } </script>

1
2
3
4
5
<script>
if (‘serviceWorker’ in navigator) {
navigator.serviceWorker.register(‘/sw.js’);
}
</script>

将保留到您的网站根目录下

在你的sw.js中修改

JavaScript

const ignoreFetch = [ /https?:\/\/cdn.bootcss.com\//,
/https?:\/\/static.duoshuo.com\//,
/https?:\/\/www.google-analytics.com\//,
/https?:\/\/dn-lbstatics.qbox.me\//, ];

1
2
3
4
5
6
const ignoreFetch = [
  /https?:\/\/cdn.bootcss.com\//,
  /https?:\/\/static.duoshuo.com\//,
  /https?:\/\/www.google-analytics.com\//,
  /https?:\/\/dn-lbstatics.qbox.me\//,
];

打开Chrome Dev Tools->Source,看看自身的blog都引用了怎么第3方能源,各个加到忽略列表里。

金沙国际 4

在根目录下添加offline.html,在未曾网络且缓存中也从没时选择,效果如下:

金沙国际 5

在根目录下添加offline.svg,在无网络时图片能源请求重返该公文。

Service Worker 是什么?

3个 service worker
是一段运行在浏览器后台进度里的剧本,它独立于当下页面,提供了这几个不必要与web页面交互的成效在网页背后悄悄执行的力量。在今后,基于它能够完成音信推送,静默更新以及地理围栏等劳务,不过当前它首先要持有的功用是阻挠和拍卖互连网请求,包含可编制程序的响应缓存管理。

缘何说这么些API是贰个卓殊棒的API呢?因为它使得开发者能够支撑尤其好的离线体验,它赋予开发者完全控制离线数据的能力。

在service worker提议从前,其余3个提供开发者离线体验的API叫做App
Cache。不过App
Cache有个别局限性,例如它能够很容易地化解单页应用的标题,可是在多页应用上会很辛苦,而Serviceworkers的面世便是为了解决App Cache的痛点。

下边详细说一下service worker有哪些要求注意的地方:

让大家初始吧

假诺你有以下 HTML 页面。那即便相当基础,但能给您完全思路。

XHTML

<!DOCTYPE html>

1
<!DOCTYPE html>

随着,让我们在页面里登记 Service Worker,那里仅创立了该对象。向刚刚的
HTML 里添加以下代码。

JavaScript

<script> // Register the service worker // 注册 service worker if
(‘serviceWorker’ in navigator) {
navigator.serviceWorker.register(‘/service-worker.js’).then(function(registration)
{ // Registration was successful // 注册成功 console.log(‘ServiceWorker
registration successful with scope: ‘, registration.scope);
}).catch(function(err) { // registration failed 🙁 // 注册战败 🙁
console.log(‘ServiceWorker registration failed: ‘, err); }); }
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
// Register the service worker
// 注册 service worker
if (‘serviceWorker’ in navigator) {
    navigator.serviceWorker.register(‘/service-worker.js’).then(function(registration) {
    // Registration was successful
    // 注册成功
    console.log(‘ServiceWorker registration successful with scope: ‘, registration.scope);
}).catch(function(err) {
    // registration failed 🙁
    // 注册失败 🙁
    console.log(‘ServiceWorker registration failed: ‘, err);
   });
}
</script>

然后,大家需求创立 Service Worker 文件并将其命名为
‘service-worker.js‘。大家打算用那一个 Service Worker
拦截任何互联网请求,以此检查互联网的连接性,并依据检查结果向用户重回最适合的始末。

JavaScript

‘use strict’; var cacheVersion = 1; var currentCache = { offline:
‘offline-cache’ + cacheVersion }; const offlineUrl =
‘offline-page.html’; this.addEventListener(‘install’, event => {
event.waitUntil( caches.open(currentCache.offline).then(function(cache)
{ return cache.addAll([ ‘./img/offline.svg’, offlineUrl ]); }) ); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
‘use strict’;
 
var cacheVersion = 1;
var currentCache = {
  offline: ‘offline-cache’ + cacheVersion
};
const offlineUrl = ‘offline-page.html’;
 
this.addEventListener(‘install’, event => {
  event.waitUntil(
    caches.open(currentCache.offline).then(function(cache) {
      return cache.addAll([
          ‘./img/offline.svg’,
          offlineUrl
      ]);
    })
  );
});

在上头的代码中,我们在设置 Service Worker
时,向缓存添加了离线页面。要是大家将代码分为几小块,可看出前几行代码中,小编为离线页面钦点了缓存版本和U智跑L。假若你的缓存有例外版本,那么您只需立异版本号即可简单地扫除缓存。在大概在第①2
行代码,作者向这一个离线页面及其能源(如:图片)发出请求。在获取成功的响应后,大家将离线页面和连锁能源充足到缓存。

于今,离线页面已存进缓存了,大家可在急需的时候检索它。在同三个 ServiceWorker 中,大家须要对无互联网时回来的离线页面添加相应的逻辑代码。

JavaScript

this.add伊夫ntListener(‘fetch’, event => { // request.mode = navigate
isn’t supported in all browsers // request.mode = naivgate
并没有博得全部浏览器的协助 // so include a check for Accept: text/html
header. // 由此对 header 的 Accept:text/html 实行核实 if
(event.request.mode === ‘navigate’ || (event.request.method === ‘GET’ &&
event.request.headers.get(‘accept’).includes(‘text/html’))) {
event.respondWith( fetch(event.request.url).catch(error => { //
Return the offline page // 重回离线页面 return caches.match(offlineUrl);
}) ); } else{ // Respond with everything else if we can //
重返任何我们能重回的东西 event.respondWith(caches.match(event.request)
.then(function (response) { return response || fetch(event.request); })
); } });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
this.addEventListener(‘fetch’, event => {
  // request.mode = navigate isn’t supported in all browsers
  // request.mode = naivgate 并没有得到所有浏览器的支持
  // so include a check for Accept: text/html header.
  // 因此对 header 的 Accept:text/html 进行核实
  if (event.request.mode === ‘navigate’ || (event.request.method === ‘GET’ && event.request.headers.get(‘accept’).includes(‘text/html’))) {
        event.respondWith(
          fetch(event.request.url).catch(error => {
              // Return the offline page
              // 返回离线页面
              return caches.match(offlineUrl);
          })
    );
  }
  else{
        // Respond with everything else if we can
        // 返回任何我们能返回的东西
        event.respondWith(caches.match(event.request)
                        .then(function (response) {
                        return response || fetch(event.request);
                    })
            );
      }
});

为了测试该意义,你能够行使 Chrome
内置的开发者工具。首先,导航到你的页面,然后一旦设置上了 ServiceWorker,就开辟 Network 标签并将节流(throttling)改为
Offline。(译者注:若将节流设置为 Offline
没意义,则可由此关闭互联网或然通过360安全警卫禁止 Chrome 访问网络)

金沙国际 6

假若你刷新页面,你应有能看到相应的离线页面!

金沙国际 7

一旦您只想大致地质度量试该意义而不想写任何代码,那么你能够访问作者已开立好的
demo。其余,上述任何代码能够在
Github repo 找到。

自家掌握用在此案例中的页面很简短,但您的离线页面则取决于你协调!假若你想深切该案例的内容,你能够为离线页面添加缓存破坏(
cache busting),如:
此案例。

试试看

您供给一个援助 Service
Worker 和 fetch
API 的浏览器。停止到本文编写时只有Chrome(手提式有线电话机版和桌面版)同时帮忙那二种 API(译者注:Opera
如今也协理那两者),不过 Firefox
非常快就要协助了(在每一日更新的本子中早就支撑了),而外 Safari
之外的具有浏览器也都在尝试。其余,service worker 只好登记在动用了
HTTPS 的网站上,theguardian.com
已经伊始稳步搬迁到 HTTPS,所以我们不得不在网站的 HTTPS
部分提供离线体验。就近期的话,大家挑选了 开发者博客 作为我们用来测试的地点。所以一旦你是在大家网站的 开发者博客 部分阅读那篇小说的话,很幸运。

当您利用支持的浏览器访问大家的 开发者博客 中的页面包车型客车时候,一切就准备伏贴了。断开你的网络连接,然后刷新一下页面。如若您自个儿没规范尝试的话,可以看一下那段 以身作则摄像(译者注:需梯子)。

增长速度效果

首页加快后,互联网请求从16降为1,加载时间从2.296s降为0.654s,获得了一下加载的结果。

金沙国际 8

基于webpagetest

查看测试结果

Service Worker的生命周期

Service worker拥有3个全然独立于Web页面包车型客车生命周期。

要让多少个service
worker在你的网站上生效,你须求先在您的网页中登记它。注册三个service
worker之后,浏览器会在后台默默运维三个service worker的安装进度。

在装置进程中,浏览器会加载并缓存一些静态能源。假诺全体的文本被缓存成功,service
worker就安装成功了。假设有任何公文加载或缓存失利,那么安装进度就会败北,service
worker就不能够被激活(也即没能安装成功)。假诺发生这么的标题,别担心,它会在下次再尝试安装。

当安装到位后,service
worker的下一步是激活,在这一等级,你还是能够升官三个service
worker的本子,具体内容我们会在后边讲到。

在激活之后,service
worker将接管全部在协调管辖域范围内的页面,可是要是一个页面是刚刚注册了service
worker,那么它这一回不会被接管,到下三遍加载页面的时候,service
worker才会生效。

当service
worker接管了页面之后,它或者有二种情状:要么被终止以节约内存,要么会处理fetch和message事件,那七个事件分别产生于3个互连网请求出现如故页面上发送了二个新闻。

下图是3个简化了的service worker初次安装的生命周期:

金沙国际 9

举行阅读

别的,还有多少个很棒的离线作用案例。如:Guardian 创设了贰个有着 crossword
puzzle(填字游戏)的离线
web 页面 –
由此,固然等待网络重连时(即已在离线状态下),也能找到一点乐趣。笔者也引进看看
Google Chrome Github
repo,它包括了不少两样的
Service Worker 案例 – 在这之中一部分行使案例也在那!

唯独,假若你想跳过上述代码,只是想差不离地通过贰个库来处理有关操作,那么本身推荐你看看
UpUp。那是八个轻量的剧本,能让您更自在地应用离线作用。

打赏扶助自个儿翻译更加多好小说,多谢!

打赏译者

行事规律

由此一段简单的
JavaScript,大家能够提醒浏览器在用户访问页面包车型地铁时候登时登记大家自个儿的
service worker。如今援助 service worker
的浏览器很少,所以为了制止不当,我们须求使用性子检查和测试。

JavaScript

if (navigator.serviceWorker) {
navigator.serviceWorker.register(‘/service-worker.js’); }

1
2
3
if (navigator.serviceWorker) {
    navigator.serviceWorker.register(‘/service-worker.js’);
}

瑟维斯 worker
安装事件的一片段,大家能够运用 新的缓存
API 来缓存大家网站中的各个内容,比如
HTML、CSS 和
JavaScript:

JavaScript

var staticCacheName = ‘static’; var version = 1; function updateCache()
{ return caches.open(staticCacheName + version) .then(function (cache) {
return cache.addAll([ ‘/offline-page.html’, ‘/assets/css/main.css’,
‘/assets/js/main.js’ ]); }); }; self.addEventListener(‘install’,
function (event) { event.waitUntil(updateCache()); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var staticCacheName = ‘static’;
var version = 1;
 
function updateCache() {
    return caches.open(staticCacheName + version)
        .then(function (cache) {
            return cache.addAll([
                ‘/offline-page.html’,
                ‘/assets/css/main.css’,
                ‘/assets/js/main.js’
            ]);
        });
};
 
self.addEventListener(‘install’, function (event) {
    event.waitUntil(updateCache());
});

当安装到位后,service worker
能够监听和控制 fetch
事件,让我们得以完全控制之后网站中产生的具备网络请求。

JavaScript

self.addEventListener(‘fetch’, function (event) {
event.respondWith(fetch(event.request)); });

1
2
3
self.addEventListener(‘fetch’, function (event) {
    event.respondWith(fetch(event.request));
});

在此间大家有很灵活的空中能够发挥,比如下边这么些典型,能够经过代码来生成我们和好的请求响应:

JavaScript

self.addEventListener(‘fetch’, function (event) { var response = new
Response(‘<h1>Hello, World!</h1>’, { headers: {
‘Content-Type’: ‘text/html’ } }); event.respondWith(response); });

1
2
3
4
5
self.addEventListener(‘fetch’, function (event) {
    var response = new Response(‘&lt;h1&gt;Hello, World!&lt;/h1&gt;’,
        { headers: { ‘Content-Type’: ‘text/html’ } });
    event.respondWith(response);
});

再有那一个,若是在缓存中找到了请求相应的缓存,大家得以一向从缓存中回到它,要是没找到的话,再经过互连网获取响应内容:

JavaScript

self.addEventListener(‘fetch’, function (event) { event.respondWith(
caches.match(event.request) .then(function (response) { return response
|| fetch(event.request); }) ); });

1
2
3
4
5
6
7
8
self.addEventListener(‘fetch’, function (event) {
    event.respondWith(
        caches.match(event.request)
            .then(function (response) {
                return response || fetch(event.request);
            })
    );
});

那正是说大家怎么行使那些职能来提供离线体验呢?

首先,在 service worker
安装进程中,大家供给把离线页面要求的 HTML 和财富文件通过 service worker
缓存下来。在缓存中,大家加载了和睦开销的 填字游戏 的
React应用 页面。之后,大家会阻止全数访问
theguardian.com
互连网请求,包括网页、以及页面中的财富文件。处理那些请求的逻辑大致如下:

  1. 当大家检查和测试到传播请求是指向我们的 HTML
    页面时,大家连年会想要提供最新的情节,所以我们会尝试把这些请求通过网络发送给服务器。

    1. 当大家从服务器获得了响应,就能够直接回到那个响应。
    2. 假若网络请求抛出了老大(比如因为用户掉线了),我们捕获那一个这么些,然后使用缓存的离线
      HTML 页面作为响应内容。
  2. 不然,当大家检查和测试到请求的不是 HTML
    的话,大家会从缓存中搜索响应的伸手内容。

    1. 一旦找到了缓存内容,大家得以一直回到缓存的始末。
    2. 不然,大家会尝试把这些请求通过互连网发送给服务器。

在代码中,大家选拔了 新的缓存
API(它是 瑟维斯 Worker API 的一部分)以及
fetch
功效(用于转移网络请求),如下所示:

JavaScript

var doesRequestAcceptHtml = function (request) { return
request.headers.get(‘Accept’) .split(‘,’) .some(function (type) { return
type === ‘text/html’; }); }; self.addEventListener(‘fetch’, function
(event) { var request = event.request; if
(doesRequestAcceptHtml(request)) { // HTML pages fallback to offline
page event.respondWith( fetch(request) .catch(function () { return
caches.match(‘/offline-page.html’); }) ); } else { // Default fetch
behaviour // Cache first for all other requests event.respondWith(
caches.match(request) .then(function (response) { return response ||
fetch(request); }) ); } });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var doesRequestAcceptHtml = function (request) {
    return request.headers.get(‘Accept’)
        .split(‘,’)
        .some(function (type) { return type === ‘text/html’; });
};
 
self.addEventListener(‘fetch’, function (event) {
    var request = event.request;
    if (doesRequestAcceptHtml(request)) {
        // HTML pages fallback to offline page
        event.respondWith(
            fetch(request)
                .catch(function () {
                    return caches.match(‘/offline-page.html’);
                })
        );
    } else {
        // Default fetch behaviour
        // Cache first for all other requests
        event.respondWith(
            caches.match(request)
                .then(function (response) {
                    return response || fetch(request);
                })
        );
    }
});

就只供给这么多!theguardian.com
上的 抱有代码都是在 GitHub
上开源 的,所以您可以去那儿查看大家的
service worker
的完全版本,恐怕直接从生产条件上访问

我们有丰富的说辞为这么些新的浏览器技术欢呼喝彩,因为它能够用来让您的网站像前几日的原生应用相同,拥有完善的离线体验。以往当
theguardian.com 完全迁移到 HTTPS
之后,离线页面包车型客车严重性性会分明增多,大家得以提供越来越完善的离线体验。设想一下你在上下班路上互连网很差的时候访问
theguardian.com,你会看到专门为您订制的本性化内容,它们是在你以前访问网站时由浏览器缓存下来的。它在设置进度中也不会发生任何困难,你所急需的只是造访那几个网站而已,不像原生应用,还索要用户有二个利用集团的账号才能设置。Serviceworker
同样可以协理大家进步网站的加载速度,因为网站的框架能够被保证地缓存下来,就像是原生应用相同。

只要您对 service worker
很感兴趣,想要精通越来越多内容的话,开发者 MattGaunt(Chrome的忠诚支持者)写了一篇特别详实地 介绍 Service
Worker的文章。

打赏协理本人翻译越多好文章,多谢!

打赏译者

加速/离线原理探索

在大家开始写码在此之前

从这个品种地址拿到chaches
polyfill。

这个polyfill支持CacheStorate.match,Cache.add和Cache.addAll,而现在Chrome
M40实现的Cache
API还尚无帮助这几个方式。

将dist/serviceworker-cache-polyfill.js放到你的网站中,在service
worker中通过importScripts加载进来。被service
worker加载的脚本文件会被活动缓存。

JavaScript

importScripts(‘serviceworker-cache-polyfill.js’);

1
importScripts(‘serviceworker-cache-polyfill.js’);

需要HTTPS

在开发阶段,你能够透过localhost使用service
worker,但是一旦上线,就必要您的server帮忙HTTPS。

您能够经过service
worker威胁连接,伪造和过滤响应,相当逆天。纵然你能够约束自个儿不干坏事,也会有人想干坏事。所以为了制止旁人使坏,你只可以在HTTPS的网页上注册service
workers,那样大家才足以预防加载service
worker的时候不被坏人篡改。(因为service
worker权限非常大,所以要预防它本身被坏人篡改利用——译者注)

Github
Pages正巧是HTTPS的,所以它是叁个可以的原生态实验田。

假设你想要让您的server援救HTTPS,你须求为你的server获得三个TLS证书。分化的server安装方法不一样,阅读扶助文书档案并由此Mozilla’s
SSL config
generator询问最佳实践。

打赏帮衬本人翻译更多好文章,感激!

任选一种支付格局

金沙国际 10
金沙国际 11

1 赞 3 收藏 1
评论

打赏协助作者翻译越来越多好文章,谢谢!

金沙国际 12

1 赞 收藏
评论

什么是 Service worker

金沙国际 13

如上图,Service
worker

是一种由Javascript编写的浏览器端代理脚本,位于你的浏览器和服务器之间。当1个页面注册了三个
Service
worker
,它就足以登记一多重事件处理器来响应如网络请求和新闻推送这几个事件。Service
worker

能够被用来治本缓存,当响应2个网络请求时方可配备为回到缓存如故从网络获取。由于Service
worker

是依照事件的,所以它只在处理那几个事件的时候被调入内部存款和储蓄器,不用顾虑常驻内部存款和储蓄器占用能源导致系统变慢。

使用Service Worker

当今我们有了polyfill,并且解决了HTTPS,让大家看看毕竟怎么用service
worker。

关于笔者:刘健超-J.c

金沙国际 14

前端,在路上…
个人主页 ·
笔者的小说 ·
19 ·
    

金沙国际 15

有关小编:Erucy

金沙国际 16

早就的SharePoint喵星程序猿(暂且还挂着微软MVP的名头),今后的Azure/.Net/MongoDB/Cordova/前端程序猿,偶尔写随笔
个人主页 ·
作者的文章 ·
46 ·
  

金沙国际 17

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图