菜单

利用 Service worker 创立二个非常简单的离线页面

2019年4月11日 - XML

Cache

网页缓存有不可计数,如HTTP缓存,localStorage,sessionStorage和cacheStorage都得以灵活搭配举行缓存,但操作太繁琐,直接运用越来越尖端Service
worker

–本文的主人。

有关作者:刘健超-J.c

图片 1

前端,在路上…http://jchehe.github.io
个人主页
·
笔者的篇章
·
19
·
    

图片 2

加速/离线原理探索

展开阅读

别的,还有多少个很棒的离线功效案例。如:Guardian 创设了一个兼有 crossword
puzzle
(填字游戏)的离线
web 页面 –
由此,即便等待网络重连时(即已在离线状态下),也能找到一点乐趣。小编也引入看看
Google Chrome Github
repo
,它包罗了累累例外的
Service Worker 案例 – 在那之中有个别利用案例也在那!

但是,假诺你想跳过上述代码,只是想大约地经过二个库来处理有关操作,那么自个儿推荐你看看
UpUp。那是1个轻量的台本,能让您更轻松地利用离线功能。

打赏帮助笔者翻译更加多好作品,感激!


打赏译者

activate

JavaScript

/////////// // Activate /////////// function onActivate(event) {
log(‘activate event in progress.’); event.waitUntil(removeOldCache()); }
function removeOldCache() { return caches .keys() .then((keys) => {
return Promise.all( // We return a promise that settles when all
outdated caches are deleted. keys .filter((key) => { return
!key.startsWith(version); // Filter by keys that don’t start with the
latest version prefix. }) .map((key) => { return caches.delete(key);
// Return a promise that’s fulfilled when each outdated cache is
deleted. }) ); }) .then(() => { log(‘removeOldCache completed.’); });
}

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
///////////
// Activate
///////////
function onActivate(event) {
  log(‘activate event in progress.’);
  event.waitUntil(removeOldCache());
}
function removeOldCache() {
  return caches
    .keys()
    .then((keys) => {
      return Promise.all( // We return a promise that settles when all outdated caches are deleted.
        keys
         .filter((key) => {
           return !key.startsWith(version); // Filter by keys that don’t start with the latest version prefix.
         })
         .map((key) => {
           return caches.delete(key); // Return a promise that’s fulfilled when each outdated cache is deleted.
         })
      );
    })
    .then(() => {
      log(‘removeOldCache completed.’);
    });
}

在activate时依据version值来删除过期的缓存。

打赏支持自身翻译越来越多好文章,多谢!

任选1种支付形式

图片 3
图片 4

1 赞 3 收藏 1
评论

管理 Service worker

应用 Service worker 创立三个分外简单的离线页面

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

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

让大家想像以下景况:大家那时候在1辆通往农村的列车上,用运动装备看着1篇很棒的篇章。与此同时,当你点击“查看越多”的链接时,火车忽然进入了隧道,导致移动设备失去了网络,而
web 页面会展现出类似以下的剧情:

图片 5

那是卓绝让人心寒的心得!幸运的是,web
开发者们能因而有个别新特征来立异这类的用户体验。作者最近间接在折腾 ServiceWorkers,它给 web 带来的无尽恐怕性总能给自家惊喜。Service Workers
的理想特质之1是同意你检查评定互连网请求的场景,并让你作出相应的响应。

在那篇小说里,小编打算用此个性检查用户的近年来互连网连接情形,假如没连接则赶回二个最好简单的离线页面。尽管这是贰个那多少个基础的案例,但它能给您带来启发,让你明白运维并运转该天性是何其的简练!即使您没领悟过
Service Worker,笔者提出你看看此 Github
repo
,理解越来越多相关的信息。

在本案例初叶前,让我们先简单地探访它的做事流程:

  1. 在用户第3遍访问大家的页面时,我们会设置 ServiceWorker,并向浏览器的缓存添加大家的离线 HTML 页面
  2. 下一场,假如用户打算导航到另贰个 web
    页面(同1个网站下),但此时已断网,那么大家将回来已被缓存的离线
    HTML 页面
  3. 而是,假诺用户打算导航到别的1个 web
    页面,而这时候网络已连接,则能照常浏览页面

福寿康宁加速/离线

让大家开始吧

假使你有以下 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。假使您的缓存有差异版本,那么你只需立异版本号即可简单地排除缓存。在大概在第一贰行代码,笔者向这么些离线页面及其财富(如:图片)发出请求。在获得成功的响应后,大家将离线页面和相关财富丰裕到缓存。

方今,离线页面已存进缓存了,我们可在要求的时等候检查索它。在同3个 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),如:
此案例

增长速度效果

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

图片 8

基于webpagetest

查看测试结果

Service worker生命周期

图片 9

Service
worker

为网页添加二个类似于APP的生命周期,它只会响应系统事件,尽管浏览器关闭时操作系统也足以提示Service
worker
,那一点至极重要,让web
app与native app的力量变得近乎了。

Service
worker
在Register时会触发Install事件,在Install时能够用来预先获取和缓存应用所需的财富并安装每一个文件的缓存策略。

一旦Service
worker
高居activated状态,就能够完全控制应用的财富,对网络请求举行检查,修改网络请求,从互联网上得到并回到内容恐怕重回由已设置的Service
worker
预先报告获取并缓存好的财富,甚至仍是能够转变内容并赶回给网络语法。

拥有的那些都用户都是晶莹的,事实上,三个统一筹划美貌的Service
worker
就如3个智能缓存系统,抓好了网络和缓存效率,选取最优办法来响应互联网请求,让使用越发平静的运维,固然未有网络也没提到,因为你能够完全控制互连网响应。

更多

TODO:

加紧/离线访问只需三步

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>

https://alphayang.github.io/sw.js封存到你的网址根目录下

在你的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都引用了如何第二方财富,每一种加到忽略列表里。

图片 10

在根目录下添加offline.html,在尚未网络且缓存中也尚辰时行使,效果如下:

图片 11

在根目录下添加offline.svg,在无互联网时图片能源请求再次回到该文件。

浏览器全局

探访你的浏览器里都有怎样Service worker已经存在了

  1. Google Chrome

在地址栏里输入:

JavaScript

chrome://serviceworker-internals/

1
chrome://serviceworker-internals/

能够见到曾经有二八个Serviceworker了,在此地能够手动Start让它工作,也足以Unregister卸载掉。

图片 12

  1. Firefox

有二种格局进入Service
worker
管理界面来手动Start或unregister。

JavaScript

about:debugging#workers

1
about:debugging#workers

图片 13

  1. Opera及别的双核浏览器同谷歌(Google) Chrome

Service worker实现

监听八个事件:

JavaScript

self.addEventListener(‘install’, onInstall);
self.addEventListener(‘fetch’, onFetch);
self.addEventListener(“activate”, onActivate);

1
2
3
self.addEventListener(‘install’, onInstall);
self.addEventListener(‘fetch’, onFetch);
self.addEventListener("activate", onActivate);

添加Service worker入口

在web app的首页添加以下代码

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>

只要浏览器帮衬serviceWorker就报了名它,不帮助照旧好端端浏览,未有Service
worker
所提供的滋长功用。

Service worker控制范围:
粗略景况下,将sw.js位居网址的根目录下,那样Service
worker
能够决定网址有着的页面,,同理,就算把sw.js放在/my-app/sw.js那么它只可以控制my-app目录下的页面。
sw.js放在/js/目录呢?越来越好的目录结构和限制控制呢?
在注册时内定js地方并设置限制。

JavaScript

navigator.serviceWorker.register(‘/js/sw.js’, {scope:
‘/sw-test/’}).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); });

1
2
3
4
5
6
7
navigator.serviceWorker.register(‘/js/sw.js’, {scope: ‘/sw-test/’}).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);
    });

特点

谷歌(Google) Chrome,Firefox,Opera以及国内的各个双核浏览器都支持,不过 safari
不扶助,那么在不协助的浏览器里Service
worker
不工作。

网址必须启用https来担保使用Service
worker
页面包车型客车安全性,开发时localhost暗中同意认为是高枕无忧的。

Service
worker

中的 Javascript 代码必须是非阻塞的,因为 localStorage
是阻塞性,所以不应当在 Service Worker 代码中央银行使 localStorage。

Service
worker
运作在本人的大局环境中,日常也运转在大团结独自的线程中。

service work能决定它所加载的任何范围内的能源。

跟DOM所处的条件是相互隔断的。

图片 14

接过系统事件,后台运转

按需实施,只在急需时加载到内部存储器

履行时会异步获取最新的版本

什么是 Service worker

图片 15

如上图,Service
worker

是壹种由Javascript编写的浏览器端代理脚本,位于你的浏览器和服务器之间。当四个页面注册了二个
Service
worker
,它就足以登记一层层事件处理器来响应如互连网请求和音讯推送这一个事件。Service
worker

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

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

动用瑟维斯 worker完毕加速/离线访问静态blog网址

2017/02/19 · JavaScript
· Service Worker

原稿出处: Yang
Bo
   

如今非常的火基于Github
page和markdown的静态blog,相当适合技术的构思和习惯,针对不相同的语言都有1对美好的静态blog系统出现,如Jekyll/Ruby,Pelican/Python,Hexo/NodeJs,由于静态内容的表征格外适合做缓存来增长速度页面的拜访,就接纳Service
worker
来达成加速,结果是除了PageSpeed,CDN那个科学普及的服务器和网络加速之外,通过客户端达成了更加好的拜会体验。

Service worker的支配从第三遍页面访问早先

在第1次加载页面时,全部财富都以从网络载的,Service
worker

在第贰次加载时不会获得控制互连网响应,它只会在接二连三访问页面时起功用。

图片 16

页面第1遍加载时形成install,并跻身idle状态。

图片 17

页面第1次加载时,进入activated状态,准备处理全部的轩然大波,同时
浏览器会向服务器发送2个异步 请求来检查Service
worker
小编是或不是有新的版本,构成了Service
worker
的更新机制。

图片 18

Service
worker
拍卖完全数的风波后,进入idle状态,最后进入terminated状态能源被保释,当有新的轩然大波产生时再一次被调用。

一定网址

  1. Google Chrome

Developer Tools->Application->Service Workers

图片 19

在那边还有七个尤其实用的复选框:

宪章断网状态

  1. Firefox

除非在Settings里有叁个得以在HTTP环境中利用Service
worker
的选项,适应于调节和测试,未有单独网址下的Service
worker
管理。

图片 20

  1. Opera及任何双核浏览器同谷歌(Google) Chrome
    壹经看到七个1律范围内的多少个Service
    worker
    ,说明Service
    woker
    更新后,而原有Service
    worker
    还从未被terminated。

Ref links

Service Worker Cookbook

Is service worker
ready?

Chrome service worker status
page

Firefox service worker status
page

MS Edge service worker status
page

WebKit service worker status
page

1 赞 2 收藏
评论

图片 21

install

JavaScript

////////// // Install ////////// function onInstall(event) {
log(‘install event in progress.’); event.waitUntil(updateStaticCache());
} function updateStaticCache() { return caches
.open(cacheKey(‘offline’)) .then((cache) => { return
cache.addAll(offlineResources); }) .then(() => { log(‘installation
complete!’); }); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//////////
// Install
//////////
function onInstall(event) {
  log(‘install event in progress.’);
  event.waitUntil(updateStaticCache());
}
function updateStaticCache() {
  return caches
    .open(cacheKey(‘offline’))
    .then((cache) => {
      return cache.addAll(offlineResources);
    })
    .then(() => {
      log(‘installation complete!’);
    });
}

install时将具备符合缓存策略的能源开始展览缓存。

fetch

JavaScript

//////// // Fetch //////// function onFetch(event) { const request =
event.request; if (shouldAlwaysFetch(request)) {
event.respondWith(networkedOrOffline(request)); return; } if
(shouldFetchAndCache(request)) {
event.respondWith(networkedOrCached(request)); return; }
event.respondWith(cachedOrNetworked(request)); }
onFetch做为浏览器网络请求的代理,依照要求再次来到网络或缓存内容,假如获得了网络内容,重临网络请求时还要开始展览缓存操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
////////
// Fetch
////////
function onFetch(event) {
  const request = event.request;
  if (shouldAlwaysFetch(request)) {
    event.respondWith(networkedOrOffline(request));
    return;
  }
  if (shouldFetchAndCache(request)) {
    event.respondWith(networkedOrCached(request));
    return;
  }
  event.respondWith(cachedOrNetworked(request));
}
onFetch做为浏览器网络请求的代理,根据需要返回网络或缓存内容,如果获取了网络内容,返回网络请求时同时进行缓存操作。

相关文章

发表评论

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

网站地图xml地图