创造二个非凡轻松的离线页面www.301.net,入门教程

1. 什么是Service Worker

Service Worker是谷歌发起的得以达成PWA(Progressive Web
App)的三个重要剧中人物,PWA是为着消除守旧Web 应用程式的弱项:

(一)未有桌面入口

(2)无法离线使用

(3)没有Push推送

那Service Worker的具身体表面现是什么样的吗?如下图所示:

www.301.net 1

ServiceWorker是在后台运行的一条服务Worker线程,上海教室作者开了七个标签页,所以显得了八个Client,不过不管开多少个页面都只有2个Worker在负责管理。这几个Worker的工作是把1部分能源缓存起来,然后拦截页面包车型大巴请求,先看下缓存Curry有未有,借使部分话就从缓存里取,响应200,反之没有的话就走正规的呼吁。具体来说,ServiceWorker结合Web App Manifest能到位以下工作(那也是PWA的检查测试专业):

www.301.net 2

席卷能够离线使用、断网时重临200、能提示用户把网址加多3个Logo到桌面上等。

第伍步:创设可用的离线页面

离线页面能够是静态的HTML,一般用于提示用户眼下乞请的页面权且无法利用。可是,我们得以提供1些足以阅读的页面链接。

Cache
API可以在main.js中选取。然则,该API使用Promise,在不协理Promise的浏览器中会失利,全数的JavaScript实行会由此深受震慑。为了制止那种气象,在造访/js/offlinepage.js的时候大家增加了1段代码来检查当前是不是在离线环境中:

/js/offlinepage.js 中以版本号为名称保存了近期的缓存,获取具备U卡宴L,删除不是页面包车型大巴U瑞虎L,将这么些U昂CoraL排序然后将拥有缓存的U陆风X捌L浮现在页面上:

// cache name const CACHE = ‘::PWAsite’, offlineURL = ‘/offline/’, list
= document.getElementById(‘cachedpagelist’); // fetch all caches
window.caches.keys() .then(cacheList => { // find caches by and order
by most recent cacheList = cacheList .filter(cName =>
cName.includes(CACHE)) .sort((a, b) => a – b); // open first cache
caches.open(cacheList[0]) .then(cache => { // fetch cached pages
cache.keys() .then(reqList => { let frag =
document.createDocumentFragment(); reqList .map(req => req.url)
.filter(req => (req.endsWith(‘/’) || req.endsWith(‘.html’)) &&
!req.endsWith(offlineURL)) .sort() .forEach(req => { let li =
document.createElement(‘li’), a =
li.appendChild(document.createElement(‘a’)); a.setAttribute(‘href’,
req); a.textContent = a.pathname; frag.appendChild(li); }); if (list)
list.appendChild(frag); }); }) });

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
38
39
40
41
42
43
44
45
// cache name
const
  CACHE = ‘::PWAsite’,
  offlineURL = ‘/offline/’,
  list = document.getElementById(‘cachedpagelist’);
// fetch all caches
window.caches.keys()
  .then(cacheList => {
    // find caches by and order by most recent
    cacheList = cacheList
      .filter(cName => cName.includes(CACHE))
      .sort((a, b) => a – b);
    // open first cache
    caches.open(cacheList[0])
      .then(cache => {
        // fetch cached pages
        cache.keys()
          .then(reqList => {
            let frag = document.createDocumentFragment();
            reqList
              .map(req => req.url)
              .filter(req => (req.endsWith(‘/’) || req.endsWith(‘.html’)) && !req.endsWith(offlineURL))
              .sort()
              .forEach(req => {
                let
                  li = document.createElement(‘li’),
                  a = li.appendChild(document.createElement(‘a’));
                  a.setAttribute(‘href’, req);
                  a.textContent = a.pathname;
                  frag.appendChild(li);
              });
            if (list) list.appendChild(frag);
          });
      })
  });

打赏援助自身翻译越多好文章,多谢!

任选一种支付方式

www.301.net 3
www.301.net 4

1 赞 3 收藏 1
评论

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,从扭转的Logo张开就会像展开八个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缓存:
www.301.net 5把start_url指向的页面用ServiceWorker缓存起来,那样当用户用Chrome浏览器张开这一个网页的时候,Chrome就会在底部弹2个唤起,询问用户是或不是把那个网页加多到桌面,如若点“增添”就会转移叁个桌面Logo,从那么些Logo点进去就像是打开三个App一样。感受如下:

www.301.net 6

正如狼狈的是Manifest近来唯有Chrome扶助,并且不得不在安卓系统上应用,IOS的浏览器无法增多3个桌面Logo,因为IOS未有开放那种API,可是本身的Safari却又是足以的。

综上,本文介绍了怎么用Service Worker结合Manifest做2个PWA离线Web
应用程式,重要是用ServiceWorker调控缓存,由于是写JS,相比灵敏,还足以与页面实行通讯,此外通过请求页面包车型大巴更新时间来推断是还是不是须要创新html缓存。ServiceWorker的包容性不是尤其好,然而前景相比较光明,浏览器都在预备援救。现阶段能够整合offline
cache的Manifest做离线应用。

相关阅读:

  1. 干什么要把网址升级到HTTPS
  2. 如何把网址晋级到http/二
  3. 本身是何等让网址用上HTML5Manifest

1 赞 1 收藏
评论

www.301.net 7

其三步:创设2个 Service Worker

Service Worker
是一个可编制程序的服务器代理,它能够阻挡或然响应网络请求。Service Worker
是坐落应用程序根目录的二个个的JavaScript文件。

你供给在页面对应的JavaScript文件中注册该ServiceWorker:

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

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

假设您不须要离线的连带功效,您能够只成立3个 /service-worker.js文本,那样用户就足以一向设置您的Web应用了!

ServiceWorker这几个定义或然比较难懂,它事实上是二个行事在其他线程中的标准的Worker,它无法访问页面上的DOM成分,未有页面上的API,不过足以阻止全部页面上的互连网请求,包涵页面导航,请求财富,Ajax请求。

地方就是利用全站HTTPS的关键原因了。若是你未有在您的网址中选拔HTTPS,二个第一方的剧本就能够从其余的域名注入他自个儿的ServiceWorker,然后篡改全部的请求——那确实是十分惊恐的。

Service Worker 会响应多个事件:install,activate和fetch。

进展阅读

除此以外,还有多少个很棒的离线功能案例。如:Guardian 营造了三个持有 crossword
puzzle(填字游戏)的离线
web 页面 –
因而,尽管等待互联网重连时(即已在离线状态下),也能找到一点乐趣。笔者也引入看看
Google Chrome Github
repo,它蕴涵了众多不如的
Service Worker 案例 – 当中一部分选择案例也在那!

而是,假设你想跳过上述代码,只是想大致地因此八个库来处理有关操作,那么本身推荐你看看
UpUp。那是贰个轻量的台本,能让您更轻易地利用离线功用。

打赏帮忙本人翻译更加多好小说,多谢!

打赏译者

(二)Service Worker安装和激活

注册完之后,ServiceWorker就会进行安装,这一年会触发install事件,在install事件之中能够缓存一些能源,如下sw-三.js:

JavaScript

const CACHE_NAME = “fed-cache”; this.add伊芙ntListener(“install”,
function(event) { this.skipWaiting(); console.log(“install service
worker”); // 创立和开辟3个缓存库 caches.open(CACHE_NAME); // 首页 let
cacheResources = [“];
event.waitUntil( // 请求能源并加多到缓存里面去
caches.open(CACHE_NAME).then(cache => {
cache.addAll(cacheResources); }) ); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const CACHE_NAME = "fed-cache";
this.addEventListener("install", function(event) {
    this.skipWaiting();
    console.log("install service worker");
    // 创建和打开一个缓存库
    caches.open(CACHE_NAME);
    // 首页
    let cacheResources = ["https://fed.renren.com/?launcher=true"];
    event.waitUntil(
        // 请求资源并添加到缓存里面去
        caches.open(CACHE_NAME).then(cache => {
            cache.addAll(cacheResources);
        })
    );
});

经过地点的操作,创造和加多了三个缓存库叫fed-cache,如下Chrome调整台所示:

www.301.net 8

ServiceWorker的API基本上都是再次回到Promise对象制止堵塞,所以要用Promise的写法。上边在设置ServiceWorker的时候就把首页的请求给缓存起来了。在ServiceWorker的运作条件之中它有一个caches的大局对象,这些是缓存的入口,还有贰个常用的clients的大局对象,一个client对应一个标签页。

在ServiceWorker里面能够运用fetch等API,它和DOM是隔断的,未有windows/document对象,不能够直接操作DOM,不能够直接和页面交互,在ServiceWorker里面不能够获悉当前页面展开了、当前页面包车型地铁url是何许,因为贰个ServiceWorker管理当前开采的多少个标签页,能够经过clients知道全部页面包车型地铁url。还有能够经过postMessage的艺术和主页面互相传递新闻和数码,进而做些调整。

install完以往,就会触发瑟维斯 Worker的active事件:

JavaScript

this.addEventListener(“active”, function(event) { console.log(“service
worker is active”); });

1
2
3
this.addEventListener("active", function(event) {
    console.log("service worker is active");
});

ServiceWorker激活之后就能够监听fetch事件了,大家盼望每获得二个能源就把它缓存起来,就无须像上一篇涉嫌的Manifest须要先生成1个列表。

您恐怕会问,当本人刷新页面包车型客车时候不是又再次登记安装和激活了三个ServiceWorker?即便又调了一回注册,但并不会重新挂号,它发现”sw-3.js”那一个已经注册了,就不会再登记了,进而不会触发install和active事件,因为目前ServiceWorker已经是active状态了。当必要立异ServiceWorker时,如形成”sw-四.js”,可能退换sw-3.js的文书内容,就会再一次注册,新的ServiceWorker会先install然后进入waiting状态,等到重启浏览器时,老的ServiceWorker就会被轮换掉,新的ServiceWorker进入active状态,假诺不想等到再次起动浏览器能够像上边一样在install里面调skipWaiting:

JavaScript

this.skipWaiting();

1
this.skipWaiting();

小结

至今,相信您假诺依照本文一步一步操作下来,你也得以急速把本身的Web应用转为PWA。在转为了PWA后,假使有利用满意PWA
模型的前端控件的急需,你能够执行纯前端表格控件SpreadJS,适用于
.NET、Java 和移动端等楼台的报表控件一定不会令你失望的。

原作链接:

1 赞 1 收藏
评论

www.301.net 7

行使 Service worker 成立2个相当轻便的离线页面

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

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

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

www.301.net 10

那是1对1令人心寒的体会!幸运的是,web
开荒者们能由此1些新特色来革新那类的用户体验。笔者近年径直在折腾 ServiceWorkers,它给 web 带来的不知凡几或许性总能给自身惊奇。Service Workers
的优异特质之壹是允许你检查测试互联网请求的场所,并让您作出相应的响应。

在那篇小说里,笔者打算用此天性检查用户的当前网络连接处境,假使没连接则赶回三个最棒轻松的离线页面。尽管那是三个至极基础的案例,但它能给您带来启迪,让您精通运转并运营该性子是多么的简练!借使您没驾驭过
Service Worker,笔者提议你看看此 Github
repo,通晓越来越多相关的音信。

在该案例初叶前,让大家先简单地看望它的办事流程:

  1. 在用户第3次访问我们的页面时,我们会设置 ServiceWorker,并向浏览器的缓存增加我们的离线 HTML 页面
  2. 然后,如若用户打算导航到另三个 web
    页面(同三个网址下),但那时已断网,那么大家将回来已被缓存的离线
    HTML 页面
  3. 可是,假如用户打算导航到此外多个 web
    页面,而那时候网络已连接,则能照常浏览页面

4. Http/Manifest/Service Worker三种cache的关系

要缓存能够利用两种手腕,使用Http
Cache设置缓存时间,也足以用Manifest的Application Cache,还足以用ServiceWorker缓存,假诺三者都用上了会怎么着呢?

会以Service Worker为预先,因为ServiceWorker把请求拦截了,它首先做处理,假诺它缓存库里有个别话一向回到,未有的话符合规律请求,就相当于尚未ServiceWorker了,这一年就到了Manifest层,Manifest缓存里如果部分话就取那个缓存,若是未有的话就一定于尚未Manifest了,于是就会从Http缓存里取了,要是Http缓存里也从不就会发请求去获取,服务端依据Http的etag或许Modified
Time或然会重返30肆 Not
Modified,不然符合规律再次回到200和数量内容。那正是整四个收获的进度。

就此只要既用了Manifest又用ServiceWorker的话应该会导致同1个能源存了五回。但是足以让帮忙ServiceWorker的浏览器选用Service Worker,而不支持的行使Manifest.

开垦者工具

Chrome浏览器提供了一多元的工具来接济您来调控ServiceWorker,日志也会直接展现在调控台上。

您最佳利用匿有名的模特式来拓展支付工作,那样能够解除缓存对开采的困扰。

最后,Chrome的Lighthouse恢宏也得感到你的渐进式Web应用提供部分立异音信。

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

www.301.net 11

前端,在路上…
个人主页 ·
作者的文章 ·
19 ·
    

www.301.net 7

3. 使用Service Worker

ServiceWorker的行使套路是先登记1个Worker,然后后台就会运维一条线程,能够在那条线程运维的时候去加载一些财富缓存起来,然后监听fetch事件,在那些事件里拦截页面包车型地铁乞求,先看下缓存里有未有,假设有一贯回到,不然平日加载。可能是一同头不缓存,各类财富请求后再拷贝1份缓存起来,然后下一次呼吁的时候缓存里就有了。

Activate 事件

本条事件会在service
worker被激活时发生。你只怕不要求那几个事件,可是在演示代码中,大家在该事件产生时将老的缓存全部清理掉了:

// clear old caches function clearOldCaches() { return caches.keys()
.then(keylist => { return Promise.all( keylist .filter(key => key
!== CACHE) .map(key => caches.delete(key)) ); }); } // application
activated self.addEventListener(‘activate’, event => {
console.log(‘service worker: activate’); // delete old caches
event.waitUntil( clearOldCaches() .then(() => self.clients.claim())
); });

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
// clear old caches
function clearOldCaches() {
  return caches.keys()
    .then(keylist => {
      return Promise.all(
        keylist
          .filter(key => key !== CACHE)
          .map(key => caches.delete(key))
      );
    });
}
// application activated
self.addEventListener(‘activate’, event => {
  console.log(‘service worker: activate’);
    // delete old caches
  event.waitUntil(
    clearOldCaches()
    .then(() => self.clients.claim())
    );
});

注意self.clients.claim()进行时将会把近期service
worker作为被激活的worker。

Fetch 事件
该事件将会在互联网开始请求时发起。该事件处理函数中,我们能够动用respondWith()艺术来威胁HTTP的GET请求然后回到:

  1. 从缓存中取到的财富文件
  2. 要是第二步退步,财富文件将会从网络中选择Fetch API来获得(和service
    worker中的fetch事件非亲非故)。获取到的能源将会进入到缓存中。
  3. 比方第二步和第三步均失利,将会从缓存中回到正确的财富文件。

// application fetch network data self.addEventListener(‘fetch’, event
=> { // abandon non-GET requests if (event.request.method !== ‘GET’)
return; let url = event.request.url; event.respondWith(
caches.open(CACHE) .then(cache => { return cache.match(event.request)
.then(response => { if (response) { // return cached file
console.log(‘cache fetch: ‘ + url); return response; } // make network
request return fetch(event.request) .then(newreq => {
console.log(‘network fetch: ‘ + url); if (newreq.ok)
cache.put(event.request, newreq.clone()); return newreq; }) // app is
offline .catch(() => offlineAsset(url)); }); }) ); });

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
38
39
40
41
// application fetch network data
self.addEventListener(‘fetch’, event => {
  // abandon non-GET requests
  if (event.request.method !== ‘GET’) return;
  let url = event.request.url;
  event.respondWith(
    caches.open(CACHE)
      .then(cache => {
        return cache.match(event.request)
          .then(response => {
            if (response) {
              // return cached file
              console.log(‘cache fetch: ‘ + url);
              return response;
            }
            // make network request
            return fetch(event.request)
              .then(newreq => {
                console.log(‘network fetch: ‘ + url);
                if (newreq.ok) cache.put(event.request, newreq.clone());
                return newreq;
              })
              // app is offline
              .catch(() => offlineAsset(url));
          });
      })
  );
});

offlineAsset(url)办法中选择了一些helper方法来回到正确的数码:

// 是还是不是为图片地址? let iExt = [‘png’, ‘jpg’, ‘jpeg’, ‘gif’, ‘webp’,
‘bmp’].map(f => ‘.’ + f); function isImage(url) { return
iExt.reduce((ret, ext) => ret || url.endsWith(ext), false); } //
return 重回离线财富 function offlineAsset(url) { if (isImage(url)) { //
再次回到图片 return new Response( ‘<svg role=”img” view博克斯=”0 0 400 300″
xmlns=”
d=”M0 0h400v300H0z” fill=”#eee” /><text x=”200″ y=”150″
text-anchor=”middle” dominant-baseline=”middle” font-family=”sans-serif”
font-size=”50″ fill=”#ccc”>offline</text></svg>’, {
headers: { ‘Content-Type’: ‘image/svg+xml’, ‘Cache-Control’: ‘no-store’
}} ); } else { // return page return caches.match(offlineURL); } }

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
// 是否为图片地址?
let iExt = [‘png’, ‘jpg’, ‘jpeg’, ‘gif’, ‘webp’, ‘bmp’].map(f => ‘.’ + f);
function isImage(url) {
  
  return iExt.reduce((ret, ext) => ret || url.endsWith(ext), false);
  
}
  
  
// return 返回离线资源
function offlineAsset(url) {
  
  if (isImage(url)) {
  
    // 返回图片
    return new Response(
      ‘<svg role="img" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title>offline</title><path d="M0 0h400v300H0z" fill="#eee" /><text x="200" y="150" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="50" fill="#ccc">offline</text></svg>’,
      { headers: {
        ‘Content-Type’: ‘image/svg+xml’,
        ‘Cache-Control’: ‘no-store’
      }}
    );
  
  }
  else {
  
    // return page
    return caches.match(offlineURL);
  
  }
  
}

offlineAsset()艺术检查请求是不是为1个图纸,然后回到三个含有“offline”文字的SVG文件。别的请求将会重回offlineUEvoqueL 页面。

Chrome开荒者工具中的ServiceWorker部分提供了关于当前页面worker的新闻。当中会显得worker中暴发的荒唐,还是能够强制刷新,也能够让浏览器进入离线格局。

Cache Storage
部分例举了脚下怀有曾经缓存的能源。你能够在缓存需求革新的时候点击refresh开关。

让大家伊始吧

1经你有以下 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
      ]);
    })
  );
});

在地点的代码中,我们在安装 Service Worker
时,向缓存增添了离线页面。如若大家将代码分为几小块,可旁观前几行代码中,作者为离线页面钦点了缓存版本和UCR-VL。假诺您的缓存有两样版本,那么你只需革新版本号就可以轻易地排除缓存。在大概在第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
内置的开拓者工具。首先,导航到您的页面,然后1旦设置上了 ServiceWorker,就开采 Network 标签并将节流(throttling)改为
Offline。(译者注:若将节流设置为 Offline
没意义,则可经过关闭网络恐怕经过360安然无恙警卫禁止 Chrome 访问网络)

www.301.net 13

固然您刷新页面,你应当能收六柱预测应的离线页面!

www.301.net 14

1旦您只想差不离地质度量试该意义而不想写任何代码,那么你能够访问我已开立好的
demo。别的,上述全部代码能够在
Github repo 找到。

自家掌握用在此案例中的页面很粗大略,但你的离线页面则取决于你自身!借使您想深刻该案例的剧情,你可以为离线页面增多缓存破坏(
cache busting),如:
此案例。

选用 Service Worker 做三个 PWA 离线网页应用

2017/10/09 · JavaScript
· PWA, Service
Worker

初稿出处:
人人网FED博客   

在上1篇《笔者是哪些让网址用上HTML5Manifest》介绍了怎么用Manifest做三个离线网页应用,结果被广大网上好友作弄说那个事物已经被deprecated,移出web标准了,今后被ServiceWorker代替了,不管怎么样,Manifest的有的盘算还是能借用的。小编又将网址进级到了ServiceWorker,借使是用Chrome等浏览器就用ServiceWorker做离线缓存,假若是Safari浏览器就依旧用Manifest,读者能够展开这几个网址感受一下,断网也是能健康展开。

URL隐藏

当你的施用正是三个单UWranglerL的应用程序时(比如游戏),笔者建议你隐藏地址栏。除此而外的状态笔者并不建议您隐藏地址栏。在Manifest中,display: minimal-ui 或者 display: browser对于大许多场合包车型大巴话充裕用了。

(一)注册3个瑟维斯 Worker

Service Worker对象是在window.navigator里面,如下代码:

JavaScript

window.addEventListener(“load”, function() { console.log(“Will the
service worker register?”); navigator.serviceWorker.register(‘/sw-3.js’)
.then(function(reg){ console.log(“Yes, it did.”); }).catch(function(err)
{ console.log(“No it didn’t. This happened: “, err) }); });

1
2
3
4
5
6
7
8
9
window.addEventListener("load", function() {
    console.log("Will the service worker register?");
    navigator.serviceWorker.register(‘/sw-3.js’)
    .then(function(reg){
        console.log("Yes, it did.");
    }).catch(function(err) {
        console.log("No it didn’t. This happened: ", err)
    });
});

在页面load完以往注册,注册的时候传3个js文件给它,那个js文件就是ServiceWorker的运营环境,假设不能够得逞注册的话就会抛万分,如Safari
TP固然有那几个目的,可是会抛非常不只怕选择,就足以在catch里面处理。那里有个难点是为啥须要在load事件运营呢?因为您要格外运营一个线程,运营未来你大概还会让它去加载财富,那几个都以急需占用CPU和带宽的,大家应有有限援助页面能寻常加载完,然后再起步大家的后台线程,无法与健康的页面加载爆发竞争,那几个在低级移动设备意义一点都不小。

再有少数须要注意的是ServiceWorker和Cookie同样是有Path路径的概念的,倘若您设定1个cookie尽管叫time的path=/page/A,在/page/B那个页面是不可能收获到这一个cookie的,若是设置cookie的path为根目录/,则具有页面都能取获得。类似地,假设注册的时候利用的js路线为/page/sw.js,那么这些ServiceWorker只可以管理/page路线下的页面和财富,而不可见处理/api路线下的,所以壹般把ServiceWorker注册到顶尖目录,如上边代码的”/sw-3.js”,那样这一个ServiceWorker就能接管页面包车型客车装有能源了。

缓存过大

您不能够将您网址中的全体剧情缓存下来。对于小一些的网址以来缓存全数剧情并不是3个主题材料,可是倘若一个网址包括了上千个页面吗?很鲜明不是全部人对网址中的全体剧情都感兴趣。存款和储蓄是有限制的,要是你将具备访问过的页面都缓存下来的话,缓存大小会增进额十分的快。

您能够那样制定你的缓存计谋:

  • 只缓存首要的页面,比如主页,联系人页面和近日浏览作品的页面。
  • 毫不缓存任何图片,摄像和大文件
  • 定期清理旧的缓存
  • 提供多个“离线阅读”按钮,那样用户就可以挑选供给缓存哪些内容了。

(4)cache html

下面第(3)步把图纸、js、css缓存起来了,但是借使把页面html也缓存了,例如把首页缓存了,就会有1个难堪的难题——ServiceWorker是在页面注册的,不过今后拿到页面的时候是从缓存取的,每一趟都以平等的,所以就招致力不从心立异ServiceWorker,如形成sw-伍.js,但是PWA又必要大家能缓存页面html。那如何做吧?Google的开拓者文书档案它只是提到会存在那几个标题,但并从未认证怎么消除那么些主题材料。这么些的主题材料的消除就要求大家要有一个建制能精晓html更新了,从而把缓存里的html给替换掉。

Manifest更新缓存的机制是去看Manifest的公文内容有没有发生变化,假使发生变化了,则会去立异缓存,ServiceWorker也是依据sw.js的文书内容有未有产生变化,大家能够借鉴那一个观念,借使请求的是html并从缓存里收取来后,再发个请求获取三个文书看html更新时间是还是不是发生变化,假若爆发变化了则证实产生更换了,进而把缓存给删了。所以能够在服务端通过决定这么些文件从而去创新客户端的缓存。如下代码:

JavaScript

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 ULacrosseL(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,如若是的话就去发个请求获取3个文本,依据那几个文件的内容决定是还是不是须求删除缓存,那几个立异的函数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 “

  • url); cache.delete(url, {ignoreVary: true}); }); } };
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: []}}

其间根本有贰个updateTime的字段,如若本地内部存款和储蓄器没有那一个页面包车型大巴updateTime的多少依然是和流行update提姆e不平等,则重复去赢得
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就代表那是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也不会缓存了。

还有1种更新是用户更新的,例如用户公布了评价,须求在页面布告service
worker把html缓存删了重新得到,那是1个扭转的音讯通告:

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 “

  • 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
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。用户发表完评论后会触发刷新页面,刷新的时候缓存已经被删了就会再也去央浼了。

这么就一蹴而就了实时更新的难点。

缓存刷新

示范代码中在倡导呼吁在此以前会先查询缓存。当用户处于离线状态时,这很好,可是如若用户处于在线状态,那他只会浏览到比较老旧的页面。

各样财富比如图片和视频不会转移,所以一般都把这几个静态能源设置为漫漫缓存。那一个财富能够直接缓存一年(31,53陆,000秒)。在HTTP
Header中,就是:

Cache-Control: max-age=31536000

1
Cache-Control: max-age=31536000

页面,CSS醒感戏本文件只怕转换的更频仍1些,所以您能够设置多少个相当的小的缓存超时时间(2四小时),并保障在用户互联网连接复苏时再一次从服务器请求:

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

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

你也足以在历次网址揭橥时,通过更名的方法强制浏览器重新请求财富。

(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同样就以为是同3个财富。

地方代码的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,假使跨域的能源扶助CO奇骏S,那么能够把request的mod改成cors。借使请求败北了,如404依旧是逾期等等的,那么也直接重临response让主页面处理,不然的话表明加载成功,把这一个response克隆二个放置cache里面,然后再重临response给主页面线程。注意能舒缓存里的能源一般只可以是GET,通过POST获取的是无法缓存的,所以要做个决断(当然你也得以手动把request对象的method改成get),还有把部分私人住房不希望缓存的能源也做个推断。

那样假诺用户展开过二次页面,ServiceWorker就设置好了,他刷新页面也许展开第3个页面包车型大巴时候就能够把请求的能源壹1做缓存,包蕴图片、CSS、JS等,只要缓存里有了不管用户在线或许离线都能够健康访问。那样我们本来会有贰个主题材料,这几个缓存空间到底有多大?上一篇大家提到Manifest也究竟地点存款和储蓄,PC端的Chrome是5Mb,其实那些说法在新本子的Chrome已经不标准了,在Chrome
六一版本能够看来地点存款和储蓄的半空大壮应用状态:

www.301.net 15

里头Cache Storage是指ServiceWorker和Manifest占用的空间大小和,上海体育地方能够看看总的空间尺寸是20GB,大致是unlimited,所以基本上不用操心缓存会不够用。

第一步:使用HTTPS

渐进式Web应用程序须要使用HTTPS连接。即使采纳HTTPS会让您服务器的支出变多,但使用HTTPS能够让你的网站变得更安全,HTTPS网址在谷歌上的排行也会更靠前。

出于Chrome浏览器会暗中同意将localhost以及1二7.x.x.x地方视为测试地方,所以在本示例中您并不要求开启HTTPS。其余,出于调节和测试目标,您能够在运行Chrome浏览器的时候利用以下参数来关闭其对网址HTTPS的反省:

  • –user-data-dir
  • –unsafety-treat-insecure-origin-as-secure

二. Service Worker的支撑景况

瑟维斯 Worker最近只有Chrome/Firfox/Opera支持:

www.301.net 16

Safari和艾德ge也在备选帮助Service Worker,由于ServiceWorker是谷歌(谷歌)基本的1项正式,对于生态相比封闭的Safari来讲也是迫于时局起首准备辅助了,在Safari
TP版本,能够见见:

www.301.net 17

在实验作用(Experimental Features)里曾经有ServiceWorker的菜单项了,只是纵然张开也是无法用,会提示您还从未得以达成:

www.301.net 18

但随便如何,至少表明Safari已经准备支持ServiceWorker了。其余还是可以看到在当年20壹七年7月发表的Safari
1壹.0.一本子现已支撑WebRTC了,所以Safari依然三个上扬的孩子。

艾德ge也准备扶助,所以Service Worker的前景至比绝对漂亮好。

其次步:创造3个应用程序清单(Manifest)

应用程序清单提供了和脚下渐进式Web应用的连锁信息,如:

  • 应用程序名
  • 描述
  • 不无图片(包涵主显示屏Logo,运转显示器页面和用的图样或许网页上用的图片)

真相上讲,程序清单是页面上用到的Logo和主旨等能源的元数据。

程序清单是三个放在您使用根目录的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">

以下属性在程序清单中平时使用,介绍表达如下:

  • name: 用户观察的行使名称
  • short_name: 应用短名称。当显示采取名称的地点不够时,将利用该名称。
  • description: 采用描述。
  • start_url: 行使早先路线,相对路线,默以为/。
  • scope: U汉兰达L范围。比如:假若您将“/app/”设置为UQX56L范围时,那个应用就会直接在那几个目录中。
  • background_color: 欢迎页面包车型客车背景颜色和浏览器的背景颜色(可选)
  • theme_color: 使用的宗旨颜色,一般都会和背景颜色一样。那一个装置决定了动用怎么样体现。
  • orientation: 事先旋转方向,可选的值有:any, natural, landscape,
    landscape-primary, landscape-secondary, portrait, portrait-primary,
    and portrait-secondary
  • display: 展现情势——fullscreen(无Chrome),standalone(和原生应用同样),minimal-ui(最小的一套UI控件集)或许browser(最古老的施用浏览器标签展现)
  • icons: 三个饱含全数图片的数组。该数组中种种成分包罗了图片的U宝马7系L,大小和档次。

渐进式Web应用(PWA)入门教程(下)

2018/05/25 · 基础技巧 ·
PWA

原版的书文出处: Craig
Buckler   译文出处:赐紫牛桃城控件   

上篇小说大家对渐进式Web应用(PWA)做了有的宗旨的介绍。

渐进式Web应用(PWA)入门教程(上)

在这一节中,大家将介绍PWA的规律是如何,它是怎么着发轫职业的。

Install事件

该事件将要采纳设置实现后触发。大家一般在此间运用Cache
API缓存一些必需的公文。

率先,咱们供给提供如下配置

  1. 缓存名称(CACHE)以及版本(version)。应用可以有多少个缓存存款和储蓄,但是在采用时只会选取当中三个缓存存款和储蓄。每当缓存存款和储蓄有生成时,新的本子号将会钦赐到缓存存储中。新的缓存存储将会作为当前的缓存存储,在此之前的缓存存款和储蓄将会被作废。
  2. 八个离线的页面地址(offlineUPRADOL):当用户访问了前边并没有访问过的地址时,该页面将会显得。
  3. 3个包涵了具备必须文件的数组,包含保持页面常常职能的CSS和JavaScript。在本示例中,小编还增加了主页和logo。当有例外的ULX570L指向同一个财富时,你也能够将那些U昂CoraL分别写到这么些数组中。offlineU安德拉L将会投入到那一个数组中。
  4. 咱俩也能够将一些非要求的缓存文件(installFilesDesirable)。那个文件在装置进程上校会被下载,但倘诺下载失利,不会触发安装失利。

// 配置文件 const version = ‘一.0.0’, CACHE = version + ‘::PWAsite’,
offlineUPRADOL = ‘/offline/’, installFilesEssential = [ ‘/’,
‘/manifest.json’, ‘/css/styles.css’, ‘/js/main.js’,
‘/js/offlinepage.js’, ‘/images/logo/logo152.png’ ].concat(offlineURL),
installFilesDesirable = [ ‘/favicon.ico’, ‘/images/logo/logo016.png’,
‘/images/hero/power-pv.jpg’, ‘/images/hero/power-lo.jpg’,
‘/images/hero/power-hi.jpg’ ];

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 配置文件
const
  version = ‘1.0.0’,
  CACHE = version + ‘::PWAsite’,
  offlineURL = ‘/offline/’,
  installFilesEssential = [
    ‘/’,
    ‘/manifest.json’,
    ‘/css/styles.css’,
    ‘/js/main.js’,
    ‘/js/offlinepage.js’,
    ‘/images/logo/logo152.png’
  ].concat(offlineURL),
  installFilesDesirable = [
    ‘/favicon.ico’,
    ‘/images/logo/logo016.png’,
    ‘/images/hero/power-pv.jpg’,
    ‘/images/hero/power-lo.jpg’,
    ‘/images/hero/power-hi.jpg’
  ];

installStaticFiles() 方法应用基于Promise的法门使用Cache
API将文件存款和储蓄到缓存中。

// 安装静态能源 function installStaticFiles() { return
caches.open(CACHE) .then(cache => { // 缓存可选文件
cache.addAll(installFilesDesirable); // 缓存必须文件 return
cache.addAll(installFilesEssential); }); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 安装静态资源
function installStaticFiles() {
  return caches.open(CACHE)
    .then(cache => {
      // 缓存可选文件
      cache.addAll(installFilesDesirable);
      // 缓存必须文件
      return cache.addAll(installFilesEssential);
    });
}

末尾,我们增加一个install的事件监听器。waitUntil措施保险了service
worker不会设置直到其息息相关的代码被实施。那里它会进行installStaticFiles()方法,然后self.skipWaiting()方法来激活service
worker:

// 应用设置 self.add伊夫ntListener(‘install’, event => {
console.log(‘service worker: install’); // 缓存首要文件 event.waitUntil(
installStaticFiles() .then(() => self.skipWaiting()) ); });

1
2
3
4
5
6
7
8
9
10
11
12
// 应用安装
self.addEventListener(‘install’, event => {
  console.log(‘service worker: install’);
  // 缓存主要文件
  event.waitUntil(
    installStaticFiles()
    .then(() => self.skipWaiting())
  );
});

渐进式Web应用的中央观念

渐进式Web应用是1种新的才干,所以使用的时候自然要小心。也正是说,渐进式Web应用能够让您的网址在多少个小时内得到改善,并且在不协助渐进式Web应用的浏览器上也不会潜移默化网址的呈现。

而是大家供给思虑以下几点:

Post Author: admin

发表评论

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