菜单

【澳门金沙投注】选择 Service worker 创造一个格外不难的离线页面

2019年2月26日 - 金沙前端

1. 什么是Service Worker

Service Worker是谷歌倡导的完毕PWA(Progressive Web
App)的2个注重角色,PWA是为了缓解守旧Web APP的缺陷:

(1)没有桌面入口

(2)不可能离线使用

(3)没有Push推送

那Service Worker的具体表现是怎样的呢?如下图所示:

澳门金沙投注 1

ServiceWorker是在后台运行的一条服务Worker线程,上海教室小编开了四个标签页,所以显得了七个Client,但是不管开多少个页面都只有多个Worker在负责管理。那么些Worker的劳作是把一部分财富缓存起来,然后拦截页面包车型大巴请求,先看下缓存Curry有没有,即使有些话就从缓存里取,响应200,反之没有的话就走不荒谬的央浼。具体来说,ServiceWorker结合Web App Manifest能不蔓不枝以下工作(那也是PWA的检查和测试标准):

澳门金沙投注 2

总结能够离线使用、断网时回来200、能唤起用户把网站添加二个图标到桌面上等。

其次步:成立七个应用程序清单(Manifest)

应用程序清单提供了和如今渐进式Web应用的相干新闻,如:

实质上讲,程序清单是页面上用到的图标和大旨等能源的元数据。

程序清单是3个身处您使用根目录的JSON文件。该JSON文件重临时务必抬高Content-Type: application/manifest+json 或者 Content-Type: application/jsonHTTP头音讯。程序清单的文本名不限,在本文的演示代码中为manifest.json

{ “name” : “PWA Website”, “short_name” : “PWA”, “description” : “An
example PWA website”, “start_url” : “/”, “display” : “standalone”,
“orientation” : “any”, “background_color” : “#ACE”, “theme_color” :
“#ACE”, “icons”: [ { “src” : “/images/logo/logo072.png”, “sizes” :
“72×72”, “type” : “image/png” }, { “src” : “/images/logo/logo152.png”,
“sizes” : “152×152”, “type” : “image/png” }, { “src” :
“/images/logo/logo192.png”, “sizes” : “192×192”, “type” : “image/png” },
{ “src” : “/images/logo/logo256.png”, “sizes” : “256×256”, “type” :
“image/png” }, { “src” : “/images/logo/logo512.png”, “sizes” :
“512×512”, “type” : “image/png” } ] }

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
28
29
30
31
32
33
34
35
36
37
{
  "name"              : "PWA Website",
  "short_name"        : "PWA",
  "description"       : "An example PWA website",
  "start_url"         : "/",
  "display"           : "standalone",
  "orientation"       : "any",
  "background_color"  : "#ACE",
  "theme_color"       : "#ACE",
  "icons": [
    {
      "src"           : "/images/logo/logo072.png",
      "sizes"         : "72×72",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo152.png",
      "sizes"         : "152×152",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo192.png",
      "sizes"         : "192×192",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo256.png",
      "sizes"         : "256×256",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo512.png",
      "sizes"         : "512×512",
      "type"          : "image/png"
    }
  ]
}

程序清单文件建立完事后,你须要在各类页面上引用该公文:

<link rel=”manifest” href=”/manifest.json”>

1
<link rel="manifest" href="/manifest.json">

以下属性在程序清单中时常应用,介绍表明如下:

有关我:刘健超-J.c

澳门金沙投注 3

前端,在路上…
个人主页 ·
小编的篇章 ·
19 ·
    

澳门金沙投注 4

Service Worker 是什么?

1个 service worker
是一段运维在浏览器后台进度里的本子,它独自于近期页面,提供了那多少个不要求与web页面交互的效用在网页背后悄悄执行的能力。在今后,基于它能够兑现新闻推送,静默更新以及地理围栏等劳务,不过近日它首先要具备的作用是掣肘和处理互联网请求,包涵可编制程序的响应缓存管理。

何以说那一个API是一个丰富棒的API呢?因为它使得开发者能够协理越发好的离线体验,它赋予开发者完全控制离线数据的能力。

在service worker提议此前,此外一个提供开发者离线体验的API叫做App
Cache。但是App
Cache某个局限性,例如它能够很不难地缓解单页应用的题材,然而在多页应用上会很劳苦,而Serviceworkers的产出便是为了消除App Cache的痛点。

下边详细说一下service worker有如何须求注意的地方:

(4)cache html

上边第(3)步把图纸、js、css缓存起来了,不过只要把页面html也缓存了,例如把首页缓存了,就会有叁个啼笑皆非的标题——ServiceWorker是在页面注册的,可是今后取得页面包车型地铁时候是从缓存取的,每一回都以千篇一律的,所以就导致力不从心立异ServiceWorker,如变成sw-5.js,不过PWA又要求我们能缓存页面html。那如何是好吧?谷歌(谷歌)的开发者文书档案它只是提到会存在这几个标题,但并不曾证实怎么消除那个难点。那一个的难题的缓解就需求我们要有2个机制能知道html更新了,从而把缓存里的html给替换掉。

Manifest更新缓存的体制是去看Manifest的文书内容有没有产生变化,假若产生变化了,则会去立异缓存,ServiceWorker也是基于sw.js的公文内容有没有产生变化,大家得以借鉴那一个思想,假如请求的是html并从缓存里取出来后,再发个请求获取3个文件看html更新时间是否发生变化,即使产生变化了则表达产生转移了,进而把缓存给删了。所以能够在服务端通过操纵那些文件从而去创新客户端的缓存。如下代码:

JavaScript

this.add伊夫ntListener(“fetch”, function(event) { event.respondWith(
caches.match(event.request).then(response => { // cache hit if
(response) { //假若取的是html,则看发个请求看html是不是更新了 if
(response.headers.get(“Content-Type”).indexOf(“text/html”) >= 0) {
console.log(“update html”); let url = new U途乐L(event.request.url);
util.updateHtmlPage(url, event.request.clone(), event.clientId); }
return response; } return util.fetchPut(event.request.clone()); }) );
});

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
this.addEventListener("fetch", function(event) {
 
    event.respondWith(
        caches.match(event.request).then(response => {
            // cache hit
            if (response) {
                //如果取的是html,则看发个请求看html是否更新了
                if (response.headers.get("Content-Type").indexOf("text/html") >= 0) {
                    console.log("update html");
                    let url = new URL(event.request.url);
                    util.updateHtmlPage(url, event.request.clone(), event.clientId);
                }
                return response;
            }
 
            return util.fetchPut(event.request.clone());
        })
    );
});

经过响应头header的content-type是或不是为text/html,借使是的话就去发个请求获取一个文件,依据那些文件的剧情决定是还是不是供给删除缓存,这几个立异的函数util.updateHtmlPage是那样完结的:

JavaScript

let pageUpdateTime = { }; let util = { updateHtmlPage: function (url,
htmlRequest) { let pageName = util.getPageName(url); let jsonRequest =
new Request(“/html/service-worker/cache-json/” + pageName + “.sw.json”);
fetch(jsonRequest).then(response => { response.json().then(content
=> { if (pageUpdateTime[pageName] !== content.updateTime) {
console.log(“update page html”); // 就算有立异则再度获得html
util.fetchPut(htmlRequest); pageUpdateTime[pageName] =
content.updateTime; } }); }); }, delCache: function (url) {
caches.open(CACHE_NAME).then(cache => { console.log(“delete cache “

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
let pageUpdateTime = {
 
};
let util = {
    updateHtmlPage: function (url, htmlRequest) {
        let pageName = util.getPageName(url);
        let jsonRequest = new Request("/html/service-worker/cache-json/" + pageName + ".sw.json");
        fetch(jsonRequest).then(response => {
            response.json().then(content => {
                if (pageUpdateTime[pageName] !== content.updateTime) {
                    console.log("update page html");
                    // 如果有更新则重新获取html
                    util.fetchPut(htmlRequest);
                    pageUpdateTime[pageName] = content.updateTime;
                }
            });
        });
    },
    delCache: function (url) {
        caches.open(CACHE_NAME).then(cache => {
            console.log("delete cache " + url);
            cache.delete(url, {ignoreVary: true});
        });
    }
};

代码先去取得四个json文件,1个页面会对应一个json文件,这几个json的内容是如此的:

JavaScript

{“updateTime”:”10/2/2017, 3:23:57 PM”,”resources”: {img: [], css:
[]}}

1
{"updateTime":"10/2/2017, 3:23:57 PM","resources": {img: [], css: []}}

个中根本有2个update提姆e的字段,借使地方内部存款和储蓄器没有那么些页面包车型大巴updateTime的数目只怕是和流行updateTime不雷同,则再度去得到html,然后放到缓存里。接着要求通告页面线程数据产生变化了,你刷新下页面吗。那样就不用等用户刷新页面才能奏效了。所以当刷新完页面后用postMessage公告页面:

JavaScript

let util = { postMessage: async function (msg) { const allClients =
await clients.matchAll(); allClients.forEach(client =>
client.postMessage(msg)); } }; util.fetchPut(htmlRequest, false,
function() { util.postMessage({type: 1, desc: “html found updated”, url:
url.href}); });

1
2
3
4
5
6
7
8
9
let util = {
    postMessage: async function (msg) {
        const allClients = await clients.matchAll();
        allClients.forEach(client => client.postMessage(msg));
    }
};
util.fetchPut(htmlRequest, false, function() {
    util.postMessage({type: 1, desc: "html found updated", url: url.href});
});

并分明type: 1就代表那是三个翻新html的音讯,然后在页面监听message事件:

JavaScript

if(“serviceWorker” in navigator) {
navigator.serviceWorker.addEventListener(“message”, function(event) {
let msg = event.data; if (msg.type === 1 && window.location.href ===
msg.url) { console.log(“recv from service worker”, event.data);
window.location.reload(); } }); }

1
2
3
4
5
6
7
8
9
if("serviceWorker" in navigator) {
    navigator.serviceWorker.addEventListener("message", function(event) {
        let msg = event.data;
        if (msg.type === 1 && window.location.href === msg.url) {
            console.log("recv from service worker", event.data);
            window.location.reload();
        }  
    });
}

下一场当大家供给更新html的时候就更新json文件,那样用户就能看到最新的页面了。大概是当用户重新开动浏览器的时候会促成ServiceWorker的周转内部存款和储蓄器都被清空了,即存款和储蓄页面更新时间的变量被清空了,这些时候也会重新请求页面。

须要注意的是,要把这一个json文件的http
cache时间设置成0,那样浏览器就不会缓存了,如下nginx的配置:

JavaScript

location ~* .sw.json$ { expires 0; }

1
2
3
location ~* .sw.json$ {
    expires 0;
}

因为那个文件是索要实时获取的,不可能被缓存,firefox私下认可会缓存,Chrome不会,加上http缓存时间为0,firefox也不会缓存了。

再有一种更新是用户更新的,例如用户公布了评价,要求在页面文告service
worker把html缓存删了再度获得,那是一个转头的音讯通告:

JavaScript

if (“serviceWorker” in navigator) {
document.querySelector(“.comment-form”).addEventListener(“submit”,
function() { navigator.serviceWorker.controller.postMessage({ type: 1,
desc: “remove html cache”, url: window.location.href} ); } }); }

1
2
3
4
5
6
7
8
9
10
if ("serviceWorker" in navigator) {
    document.querySelector(".comment-form").addEventListener("submit", function() {
            navigator.serviceWorker.controller.postMessage({
                type: 1,
                desc: "remove html cache",
                url: window.location.href}
            );
        }
    });
}

Service Worker也监听message事件:

JavaScript

const messageProcess = { // 删除html index 1: function (url) {
util.delCache(url); } }; let util = { delCache: function (url) {
caches.open(CACHE_NAME).then(cache => { console.log(“delete cache “

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const messageProcess = {
    // 删除html index
    1: function (url) {
        util.delCache(url);
    }
};
 
let util = {
    delCache: function (url) {
        caches.open(CACHE_NAME).then(cache => {
            console.log("delete cache " + url);
            cache.delete(url, {ignoreVary: true});
        });
    }
};
 
this.addEventListener("message", function(event) {
    let msg = event.data;
    console.log(msg);
    if (typeof messageProcess[msg.type] === "function") {
        messageProcess[msg.type](msg.url);
    }
});

基于分歧的新闻类型调不一致的回调函数,借使是1的话便是剔除cache。用户公布完评论后会触发刷新页面,刷新的时候缓存已经被删了就会重复去恳求了。

那样就消除了实时更新的标题。

URL隐藏

当您的施用正是3个单U奇骏L的应用程序时(比如游戏),笔者提议您隐藏地址栏。除此之外的状态本人并不建议你隐藏地址栏。在Manifest中,display: minimal-ui 或者 display: browser对此大多数状态来说丰盛用了。

举办阅读

其它,还有多少个很棒的离线功用案例。如:Guardian 营造了一个存有 crossword
puzzle(填字游戏)的离线
web 页面 –
因而,即便等待网络重连时(即已在离线状态下),也能找到一点乐趣。我也引进看看
Google Chrome Github
repo,它含有了很多不一的
Service Worker 案例 – 当中有的用到案例也在那!

而是,借使您想跳过上述代码,只是想大概地经过二个库来拍卖有关操作,那么作者推荐你看看
UpUp。那是叁个轻量的台本,能让你更轻松地利用离线效能。

打赏援助自个儿翻译越多好小说,感谢!

打赏译者

改变URL Hash的Bug

在M40版本中设有1个bug,它会让页面在改动hash的时候造成service
worker甘休工作。

您能够在此间找到更加多相关的信息: 

(3)fetch资源后cache起来

一般来说代码,监听fetch事件做些处理:

JavaScript

this.addEventListener(“fetch”, function(event) { event.respondWith(
caches.match(event.request).then(response => { // cache hit if
(response) { return response; } return
util.fetchPut(event.request.clone()); }) ); });

1
2
3
4
5
6
7
8
9
10
11
12
this.addEventListener("fetch", function(event) {
    event.respondWith(
        caches.match(event.request).then(response => {
            // cache hit
            if (response) {
                return response;
            }
            return util.fetchPut(event.request.clone());
        })
    );
});

先调caches.match看一下缓存里面是或不是有了,假如有一贯回到缓存里的response,不然的话寻常请求财富并把它放到cache里面。放在缓存里能源的key值是Request对象,在match的时候,需求请求的url和header都平等才是同一的财富,能够设定第②个参数ignoreVary:

JavaScript

caches.match(event.request, {ignoreVary: true})

1
caches.match(event.request, {ignoreVary: true})

表示一旦请求url相同就觉着是同三个能源。

地点代码的util.fetchPut是如此完毕的:

JavaScript

let util = { fetchPut: function (request, callback) { return
fetch(request).then(response => { // 跨域的财富直接return if
(!response || response.status !== 200 || response.type !== “basic”) {
return response; } util.putCache(request, response.clone()); typeof
callback === “function” && callback(); return response; }); }, putCache:
function (request, resource) { // 后台不要缓存,preview链接也毫不缓存 if
(request.method === “GET” && request.url.indexOf(“wp-admin”) < 0 &&
request.url.indexOf(“preview_id”) < 0) {
caches.open(CACHE_NAME).then(cache => { cache.put(request,
resource); }); } } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let util = {
    fetchPut: function (request, callback) {
        return fetch(request).then(response => {
            // 跨域的资源直接return
            if (!response || response.status !== 200 || response.type !== "basic") {
                return response;
            }
            util.putCache(request, response.clone());
            typeof callback === "function" && callback();
            return response;
        });
    },
    putCache: function (request, resource) {
        // 后台不要缓存,preview链接也不要缓存
        if (request.method === "GET" && request.url.indexOf("wp-admin") < 0
              && request.url.indexOf("preview_id") < 0) {
            caches.open(CACHE_NAME).then(cache => {
                cache.put(request, resource);
            });
        }
    }
};

内需小心的是跨域的能源不能缓存,response.status会重返0,即使跨域的财富支撑COENCORES,那么可以把request的mod改成cors。固然请求战败了,如404只怕是过期等等的,那么也直接重回response让主页面处理,不然的话表达加载成功,把这些response克隆2个平放cache里面,然后再重临response给主页面线程。注意能舒缓存里的能源一般只好是GET,通过POST获取的是无法缓存的,所以要做个判断(当然你也能够手动把request对象的method改成get),还有把部分私家不希望缓存的财富也做个判断。

这么一旦用户打开过二回页面,ServiceWorker就设置好了,他刷新页面大概打开第四个页面包车型客车时候就能够把请求的能源一一做缓存,包涵图片、CSS、JS等,只要缓存里有了不管用户在线恐怕离线都能够健康访问。那样我们自然会有一个难题,那么些缓存空间到底有多大?上一篇大家提到Manifest也总算地方存款和储蓄,PC端的Chrome是5Mb,其实那些说法在新本子的Chrome已经不准确了,在Chrome
61版本能够见到当地存款和储蓄的空中和应用景况:

澳门金沙投注 5

中间Cache Storage是指ServiceWorker和Manifest占用的空间尺寸和,上图能够看出总的空间尺寸是20GB,大约是unlimited,所以基本上不用操心缓存会不够用。

小结

迄今,相信你一旦遵照本文一步一步操作下来,你也可以便捷把自身的Web应用转为PWA。在转为了PWA后,假使有应用满足PWA
模型的前端控件的需要,你能够尝试纯前端表格控件SpreadJS,适用于
.NET、Java 和移动端等楼台的表格控件一定不会令你失望的。

原文链接:

1 赞 1 收藏
评论

澳门金沙投注 6

运用 Service worker 成立一个卓殊不难的离线页面

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

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

让大家想像以下景况:大家那儿在一辆通往农村的列车上,用移动设备望着一篇很棒的稿子。与此同时,当您点击“查看更加多”的链接时,火车忽然进入了隧道,导致运动装备失去了网络,而
web 页面会彰显出类似以下的始末:

澳门金沙投注 7

那是一定令人颓丧的心得!幸运的是,web
开发者们能透过有个别新特色来改进那类的用户体验。作者近年径直在折腾 ServiceWorkers,它给 web 带来的无尽大概性总能给本身惊喜。Service Workers
的优质特质之一是允许你检查和测试互联网请求的面貌,并让您作出相应的响应。

在那篇文章里,作者打算用此性情检查用户的眼下网络连接景况,如若没连接则赶回二个特级不难的离线页面。固然那是2个要命基础的案例,但它能给你带来启迪,让您了解运转并运营该天性是多么的简单!即使你没精晓过
Service Worker,笔者提出您看看此 Github
repo,精晓越多相关的消息。

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

  1. 在用户第一回访问大家的页面时,我们会安装 ServiceWorker,并向浏览器的缓存添加大家的离线 HTML 页面
  2. 然后,要是用户打算导航到另三个 web
    页面(同三个网站下),但那时已断网,那么我们将回来已被缓存的离线
    HTML 页面
  3. 唯独,借使用户打算导航到其它3个 web
    页面,而那时候互连网已连接,则能照常浏览页面

拍卖响应式图片

img的srcset属性或许<picture>标签会根据情况从浏览器或者网络上选择最合适尺寸的图片。

在service worker中,你想要在install步骤缓存3个图形,你有以下两种采取:

  1. 设置具有的<picture>元素或者将被请求的srcset属性。
  2. 安装单一的low-res版本图片
  3. 设置单一的high-res版本图片

正如好的方案是2或3,因为一旦把具有的图片都给下载下来存着有点浪费内部存款和储蓄器。

若果你将low-res版本在install的时候缓存了,然后在页面加载的时候你想要尝试从网络上下载high-res的本子,不过假如high-res版本下载失利以来,就仍旧用low-res版本。那么些想法很好也值得去做,可是有2个题目:

如若大家有下边二种图片:

Screen Density Width Height
1x 400 400
2x 800 800

HTML代码如下:

JavaScript

<img src=”image-src.png” srcset=”image-src.png 1x, image-2x.png 2x”
/>

1
<img src="image-src.png" srcset="image-src.png 1x, image-2x.png 2x" />

比方我们在3个2x的显得形式下,浏览器会下载image-2x.png,倘使我们离线,你能够读取此前缓存并赶回image-src.png替代,要是在此之前它早已被缓存过。固然如此,由于现行反革命的格局是2x,浏览器会把400X400的图样体现成200X200,要幸免那个标题即将在图纸的体制上设置宽高。

JavaScript

<img src=”image-src.png” srcset=”image-src.png 1x, image-2x.png 2x”
style=”width:400px; height: 400px;” />

1
2
<img src="image-src.png" srcset="image-src.png 1x, image-2x.png 2x"
style="width:400px; height: 400px;" />

澳门金沙投注 8

<picture>标签情况更复杂一些,难度取决于你是如何创建和使用的,但是可以通过与srcset类似的思路去解决。

3. 使用Service Worker

ServiceWorker的利用套路是先登记3个Worker,然后后台就会运维一条线程,可以在这条线程运转的时候去加载一些能源缓存起来,然后监听fetch事件,在那么些事件里拦截页面包车型地铁恳求,先看下缓存里有没有,就算有一贯回到,不然寻常加载。大概是一初步不缓存,每一个能源请求后再拷贝一份缓存起来,然后下三回呼吁的时候缓存里就有了。

第一步:使用HTTPS

渐进式Web应用程序须要利用HTTPS连接。即便使用HTTPS会让你服务器的付出变多,但利用HTTPS可以让您的网站变得更安全,HTTPS网站在谷歌(Google)上的排名也会更靠前。

是因为Chrome浏览器会暗中认可将localhost以及127.x.x.x地址视为测试地方,所以在本示例中您并不要求开启HTTPS。此外,出于调节和测试目标,您能够在开发银行Chrome浏览器的时候利用以下参数来关闭其对网站HTTPS的自我批评:

打赏帮衬我翻译越来越多好文章,谢谢!

任选一种支付办法

澳门金沙投注 9
澳门金沙投注 10

1 赞 3 收藏 1
评论

假设设置战败了,没有很优雅的不二法门拿到通报

比方三个worker被登记了,然而没有出今后chrome://inspect/#service-workers或chrome://serviceworker-internals,那么很可能因为异常而安装失败了,或者是产生了一个被拒绝的的promise给event.waitUtil。

要消除这类难点,首先到 chrome://serviceworker-internals检查。打开开发者工具窗口准备调试,然后在你的install event代码中添加debugger;语句。这样,通过断点调试你更容易找到问题。

5. 接纳Web App Manifest添加桌面入口

留意那里说的是其余贰个Manifest,那些Manifest是一个json文件,用来放网站icon名称等音讯以便在桌面添加二个图标,以及创设一种打开那么些网页就像是打开App一样的功用。上面平素说的Manifest是被撇下的Application
Cache的Manifest。

以此Maifest.json文件能够如此写:

JavaScript

{ “short_name”: “人人FED”, “name”: “人人网FED,专注于前者技术”,
“icons”: [ { “src”: “/html/app-manifest/logo_48.png”, “type”:
“image/png”, “sizes”: “48×48” }, { “src”:
“/html/app-manifest/logo_96.png”, “type”: “image/png”, “sizes”: “96×96”
}, { “src”: “/html/app-manifest/logo_192.png”, “type”: “image/png”,
“sizes”: “192×192” }, { “src”: “/html/app-manifest/logo_512.png”,
“type”: “image/png”, “sizes”: “512×512” } ], “start_url”:
“/?launcher=true”, “display”: “standalone”, “background_color”:
“#287fc5”, “theme_color”: “#fff” }

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
28
29
30
{
  "short_name": "人人FED",
  "name": "人人网FED,专注于前端技术",
  "icons": [
    {
      "src": "/html/app-manifest/logo_48.png",
      "type": "image/png",
      "sizes": "48×48"
    },
    {
      "src": "/html/app-manifest/logo_96.png",
      "type": "image/png",
      "sizes": "96×96"
    },
    {
      "src": "/html/app-manifest/logo_192.png",
      "type": "image/png",
      "sizes": "192×192"
    },
    {
      "src": "/html/app-manifest/logo_512.png",
      "type": "image/png",
      "sizes": "512×512"
    }
  ],
  "start_url": "/?launcher=true",
  "display": "standalone",
  "background_color": "#287fc5",
  "theme_color": "#fff"
}

icon供给准备五种口径,最大须要512px *
512px的,那样Chrome会自动去挑选合适的图片。假如把display改成standalone,从变化的图标打开就会像打开七个App一样,没有浏览器地址栏那些东西了。start_url钦命打开以往的入口链接。

接下来添加2个link标签指向那么些manifest文件:

JavaScript

<link rel=”manifest” href=”/html/app-manifest/manifest.json”>

1
<link rel="manifest" href="/html/app-manifest/manifest.json">

那样组合Service Worker缓存:
澳门金沙投注 11把start_url指向的页面用瑟维斯Worker缓存起来,那样当用户用Chrome浏览器打开那几个网页的时候,Chrome就会在底部弹3个升迁,询问用户是或不是把这么些网页添加到桌面,假使点“添加”就会变卦多个桌面图标,从那几个图标点进去就如打开多少个App一样。感受如下:

澳门金沙投注 12

比较为难的是Manifest近年来唯有Chrome援助,并且只可以在安卓系统上利用,IOS的浏览器无法添加1个桌面图标,因为IOS没有开放那种API,可是本身的Safari却又是足以的。

综上,本文介绍了怎么用Service Worker结合Manifest做1个PWA离线Web
APP,主若是用ServiceWorker控制缓存,由于是写JS,相比灵敏,还足以与页面进行通讯,其它通过请求页面包车型地铁翻新时间来判定是或不是必要更新html缓存。ServiceWorker的包容性不是特地好,不过前景相比光明,浏览器都在备选帮助。现阶段能够构成offline
cache的Manifest做离线应用。

相关阅读:

  1. 为啥要把网站升级到HTTPS
  2. 怎么把网站升级到http/2
  3. 自己是什么让网站用上HTML5
    Manifest

1 赞 1 收藏
评论

澳门金沙投注 13

缓存刷新

以身作则代码中在倡导呼吁在此以前会先查询缓存。当用户处于离线状态时,那很好,不过假如用户处于在线状态,那她只会浏览到比较老旧的页面。

种种能源比如图片和录制不会改变,所以一般都把那么些静态财富设置为长时间缓存。这么些财富得以一向缓存一年(31,536,000秒)。在HTTP
Header中,正是:

Cache-Control: max-age=31536000

1
Cache-Control: max-age=31536000

页面,CSS和本子文件大概变动的更频仍一些,所以你能够安装多个相比小的缓存超时时间(24钟头),并有限支撑在用户网络连接恢复生机时再也从服务器请求:

Cache-Control: must-revalidate, max-age=86400

1
Cache-Control: must-revalidate, max-age=86400

您也能够在每回网站发表时,通过更名的主意强制浏览珍视新请求能源。

让我们开首吧

比方你有以下 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(‘瑟维斯Worker 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
      ]);
    })
  );
});

金沙娱乐官网,在地方的代码中,大家在安装 瑟维斯 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 访问互联网)

澳门金沙投注 14

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

澳门金沙投注 15

就算你只想大概地测试该意义而不想写任何代码,那么你可以访问小编已开立好的
demo。其它,上述任何代码能够在
Github repo 找到。

本人晓得用在此案例中的页面很简短,但您的离线页面则在于你协调!假设你想深远该案例的内容,你能够为离线页面添加缓存破坏(
cache busting),如:
此案例js金沙娱乐平台,。

Service Worker的生命周期

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

要让三个service
worker在你的网站上生效,你必要先在您的网页中登记它。注册贰个service
worker之后,浏览器会在后台默默运转2个service worker的安装进程。

在设置进度中,浏览器会加载并缓存一些静态能源。借使具有的文本被缓存成功,service
worker就设置成功了。若是有任何公文加载或缓存失利,那么安装进度就会失利,service
worker就不能够被激活(也即没能安装成功)。固然爆发如此的难点,别担心,它会在下次再尝试安装。

当安装完毕后,service
worker的下一步是激活,在这一等级,你还足以升官多个service
worker的版本,具体内容大家会在后边讲到。

在激活之后,service
worker将接管全部在和谐管辖域范围内的页面,但是借使2个页面是刚刚注册了service
worker,那么它那叁遍不会被接管,到下二遍加载页面的时候,service
worker才会生效。

当service
worker接管了页面之后,它或然有二种状态:要么被终止以节约内部存款和储蓄器,要么会处理fetch和message事件,那多个事件分别发生于一个网络请求出现还是页面上发送了2个音信。

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

澳门金沙投注 16

相关文章

发表评论

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

网站地图xml地图