首页vns威尼斯城官网登入 › 原文出处,Worker是PWA的核心技术

原文出处,Worker是PWA的核心技术

(2)瑟维斯 Worker安装和激活

注册完之后,ServiceWorker就能够开展安装,当时会触发install事件,在install事件之中能够缓存一些财富,如下sw-3.js:

JavaScript

const CACHE_NAME = "fed-cache"; this.add伊夫ntListener("install",
function(eventState of Qatar { this.skipWaiting(卡塔尔国; console.log("install service
worker"State of Qatar; // 创设和开垦三个缓存库 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调节台所示:

图片 1

ServiceWorker的API基本上都以回来Promise对象防止拥塞,所以要用Promise的写法。上边在设置ServiceWorker的时候就把首页的乞求给缓存起来了。在ServiceWorker的周转条件之中它有贰个caches的全局对象,那个是缓存的入口,还恐怕有二个常用的clients的大局对象,叁个client对应一个标签页。

在瑟维斯Worker里面能够动用fetch等API,它和DOM是与世鸿沟的,未有windows/document对象,无法直接操作DOM,不能够间接和页面人机联作,在ServiceWorker里面无法得悉当前页面打开了、当前页面包车型地铁url是什么样,因为叁个ServiceWorker管理当前开垦的多少个标签页,能够因而clients知道全数页面包车型地铁url。还恐怕有能够由此postMessage的艺术和主页面互相传递音信和数量,进而做些调节。

install完事后,就能够触发Service 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须求先生成一个列表。

你恐怕会问,当作者刷新页面包车型大巴时候不是又重新挂号安装和激活了四个ServiceWorker?就算又调了一回注册,但并不会重复登记,它开采”sw-3.js”这些曾经登记了,就不会再登记了,进而不会触发install和active事件,因为前段时间ServiceWorker已是active状态了。当须要改良ServiceWorker时,如形成”sw-4.js”,或然转移sw-3.js的文本内容,就能够重复登记,新的ServiceWorker会先install然后进入waiting状态,等到重启浏览器时,老的瑟维斯Worker就会被替换掉,新的瑟维斯Worker步入active状态,借使不想等到再度开动浏览器能够像上边同样在install里面调skipWaiting:

JavaScript

this.skipWaiting();

1
this.skipWaiting();

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(urlState of Qatar { 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="
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()艺术检查须求是或不是为三个图纸,然后回到二个分包“offline”文字的SVG文件。其余央浼将会回去
offlineU凯雷德L 页面。

Chrome开垦者工具中的ServiceWorker部分提供了有关当前页面worker的音信。此中会显示worker中产生的荒唐,还足以强逼刷新,也得以让浏览器步向离线方式。

Cache Storage
部分例举了近些日子具有曾经缓存的能源。你能够在缓存需求立异的时候点击refresh按键。

怎么样注册和装置service worker

要设置service
worker,你须求在你的页面上登记它。这么些手续告诉浏览器你的service
worker脚本在哪里。

JavaScript

if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.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); }); }

1
2
3
4
5
6
7
8
9
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.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);
  });
}

地方的代码检查service worker API是或不是可用,就算可用,service
worker /sw.js 被注册。

如若那几个service worker已经被登记过,浏览器会活动忽视上面包车型地铁代码。

有几个急需特意表达的是service
worker文件的门道,你势必注意到了在此个例子中,service
worker文件被放在这里个域的根目录下,那意味着service
worker和网址同源。换句话说,那些service
work将会接到那个域下的持有fetch事件。若是自身将service
worker文件注册为/example/sw.js,那么,service worker只能收到/example/路径下的fetch事件(例如: /example/page1/, /example/page2/)。

当今您能够到 chrome://inspect/#service-workers 检查service worker是否对你的网站启用了。

图片 2

当service
worker第生机勃勃版被落成的时候,你也足以在chrome://serviceworker-internals中查看,它很有用,通过它可以最直观地熟悉service worker的生命周期,不过这个功能很快就会被移到chrome://inspect/#service-workers中。

您会开采这几个意义能够很便利地在二个模仿窗口中测量试验你的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('瑟维斯Worker
registration successful with scope: ', registration.scope卡塔尔;
}卡塔尔.catch(function(errState of Qatar { // registration failed 🙁 // 注册败北 🙁
console.log('ServiceWorker registration failed: ', err卡塔尔; }State of Qatar; }
</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
时,向缓存加多了离线页面。假设大家将代码分为几小块,可阅览前几行代码中,我为离线页面钦点了缓存版本和UWranglerL。固然你的缓存有例外版本,那么您只需改过版本号就能够简单地消灭缓存。在差不离在第
12
行代码,小编向这些离线页面及其能源(如:图片)发出诉求。在获得成功的响应后,大家将离线页面和血脉相近财富丰盛到缓存。

近来,离线页面已存进缓存了,我们可在急需的时等候检查索它。在同多少个 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'State of Qatar卡塔尔(قطر‎卡塔尔 {
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 (responseState of Qatar { return response || fetch(event.request卡塔尔(قطر‎; }卡塔尔卡塔尔(قطر‎; } }State of Qatar;

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 访谈互联网)

图片 3

生龙活虎经您刷新页面,你应该能来占星应的离线页面!

图片 4

如果您只想大约地质度量试该功用而不想写任何代码,那么您能够访谈我已开立好的
demo。此外,上述全部代码能够在
Github repo 找到。

自己理解用在这里案例中的页面相当粗略,但您的离线页面则在于你和睦!要是您想深切该案例的剧情,你可感到离线页面增加缓存破坏(
cache busting),如:
此案例。

Service Worker生命周期

serviceworker的应用流程能够简简单单计算为注册--安装--激活。

登记其实就是报告浏览器serviceworkerJS文件寄放在哪些地方,然后浏览器下载、拆解解析、推行该文件,进而运行安装。这里作者创设三个app.js文件,注册代码如下,将该文件在网址的head标签里引入。

if ('serviceWorker' in navigator) {

window.addEventListener('load', function () {

navigator.serviceWorker.register

.then(function (registration) {

// 注册成功

console.log('ServiceWorker registration successful with scope: ',
registration.scope);

})

.catch(function {

// 注册战败:(

console.log('ServiceWorker registration failed: ', err);

});

});

}

当实施serviceworkerJS文件时,首先触及的是install事件,进行安装。安装的经过正是将钦赐的后生可畏部分静态财富实行离线缓存。上面是自身的sw.js文件中的安装代码:

var CACHE_VERSION = 'sw_v8';

var CACHE_FILES = [

'/js/jquery/min.js',

'/js/zui/min.js',

'/js/chanzhi.js',

];

self.addEventListener('install', function {

event.waitUntil(

caches.open(CACHE_VERSION)

.then(cache => cache.addAll(CACHE_FILES)

));

});

当安装成功后,serviceworker就能激活,这个时候就能够管理 activate 事件回调
(提供了更新缓存战术的机遇State of Qatar。并得以管理功用性的平地风波 fetch 、sync 、push

self.addEventListener('activate', function {

event.waitUntil(

caches.keys().then(function{

return Promise.all(keys.map(function{

if(key !== CACHE_VERSION){

return caches.delete;

}

}));

})

);

});

(4)cache html

上边第(3)步把图片、js、css缓存起来了,不过即使把页面html也缓存了,举个例子把首页缓存了,就能有三个难堪的难题——ServiceWorker是在页面注册的,不过今后获得页面包车型地铁时候是从缓存取的,每一趟都以平等的,所以就引致敬敏不谢改革ServiceWorker,如产生sw-5.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 UOdysseyL(event.request.url卡塔尔国;
util.updateHtmlPage(url, event.request.clone(卡塔尔, event.clientId卡塔尔; }
return response; } return util.fetchPut(event.request.clone(卡塔尔); }State of Qatar 卡塔尔(قطر‎;
}卡塔尔国;

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 "

  • 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文件,三个页面会对应叁个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的数据仍然为和新颖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 "

  • 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。客商公布完批评后会触发刷新页面,刷新的时候缓存已经被删了就能够再次去央浼了。

如此那般就一挥而就了实时更新的标题。

URL隐藏

当您的应用正是贰个单USportageL的应用程序时(比方游戏),作者提出您隐敝地址栏。除此而外的景况自己并不建议你掩盖地址栏。在Manifest中,display: minimal-ui 或者 display: browser对此绝大繁多场所包车型地铁话丰硕用了。

Non-CO昂CoraS默许不支持

暗中同意情形下,从第三方UPAJEROL跨域得到多个能源将会失利,除非对方扶持了COTiggoS。你能够增多贰个non-COCRUISERS选项到Request去防止战败。代价是如此做会回去多个“不透明”的response,意味着你无法摸清那几个央浼毕竟是成功了只怕失利了。

JavaScript

cache.addAll(urlsToPrefetch.map(function(urlToPrefetch) { return new
Request(urlToPrefetch, { mode: 'no-cors' }); })).then(function() {
console.log('All resources have been fetched and cached.'); });

1
2
3
4
5
cache.addAll(urlsToPrefetch.map(function(urlToPrefetch) {
  return new Request(urlToPrefetch, { mode: 'no-cors' });
})).then(function() {
  console.log('All resources have been fetched and cached.');
});

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

任选风流浪漫种支付方式

图片 5
图片 6

1 赞 3 收藏 1
评论

serviceworker的缓存成效

设置时,serviceworker将我们钦定的静态资源开展缓存,你恐怕会问,要是是实时的动态内容咋办,大家不容许预先将有所的文书能源提前线指挥部定好,让serviceworker缓存。那将要涉及serviceworker的阻挠HTTP央浼响应的特点了。

serviceworker拦截http央求,首先去反省恳求的财富在缓存中是或不是存在,假若存在,则直接从缓存中调用,何况不怕是无网络状态下,serviceworker也能调用缓存中的财富。假若缓存中尚无诉求的能源,则经过互联网去服务器上寻找,何况在找到并响适合时宜,serviceworker会将其存入缓存中,以备下一次再乞请时平素从缓存中调用。

图片 7serviceworker缓存流程

serviceworker文件中fetch事件代码如下:

self.addEventListener('fetch', function {

event.respondWith(

caches.match(event.request).then(function{

if{

return response;

}

var requestToCache = event.request.clone();

return fetch(requestToCache).then(

function{

if(!response || response.status !== 200){

return response;

}

var responseToCache = response.clone();

caches.open(CACHE_VERSION)

.then(function{

cache.put(requestToCache, responseToCache);

});

return response;

}

);

})

);

});

在网址前台通过浏览器开垦者工具,大家得以看下从缓存中调用财富的成效:

图片 8serviceworker缓存调用图片 9缓存文件

本身那边操作演示用的是Google浏览器,上边是各大浏览器对于serviceworker的支撑景况:

图片 10serviceworker浏览器援救意况

(1)注册一个瑟维斯 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完事后注册,注册的时候传一个js文件给它,那个js文件便是ServiceWorker的运营条件,假如无法打响注册的话就能抛格外,如Safari
TP即使有其一目的,但是会抛分外无法接收,就能够在catch里面处理。这里有个问题是怎么须要在load事件运营呢?因为你要极度运营三个线程,运维今后您也许还有恐怕会让它去加载能源,那一个都是亟需占用CPU和带宽的,大家理应有限支撑页面能健康加载完,然后再起步我们的后台线程,无法与正规的页面加载产生竞争,那几个在低级移动器械意义相当大。

再有少数急需在意的是ServiceWorker和库克ie相符是有Path路线的定义的,假使您设定二个cookie假诺叫time的path=/page/A,在/page/B这一个页面是不可能获得到那一个cookie的,假如设置cookie的path为根目录/,则有着页面都能博取到。相近地,假设注册的时候利用的js路线为/page/sw.js,那么这几个ServiceWorker只可以管理/page路径下的页面和能源,而不可以管理/api路线下的,所以通常把ServiceWorker注册到五星级目录,如上边代码的”/sw-3.js”,那样那几个瑟维斯Worker就会接管页面包车型地铁持有能源了。

其三步:创立一个 Service Worker

Service Worker
是多个可编制程序的服务器代理,它能够阻挡恐怕响应网络乞请。瑟维斯 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');
}

若果您无需离线的相关职能,您能够只开创一个 /service-worker.js文本,那样客户就足以向来设置您的Web应用了!

ServiceWorker这一个定义或许相比难懂,它实乃四个职业在其它线程中的标准的Worker,它不能采访页面上的DOM成分,未有页面上的API,但是能够阻止全数页面上的互连网诉求,满含页面导航,须要财富,Ajax乞求。

上边正是使用全站HTTPS的首要缘由了。若是你未有在你的网址中央银行使HTTPS,一个第三方的台本就足以从其余的域名注入他协调的ServiceWorker,然后点窜全体的伸手——那没有疑问是可怜危险的。

瑟维斯 Worker 会响应四个事件:install,activate和fetch。

拍卖响应式图片

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

在service worker中,你想要在install步骤缓存一个图形,你有以下两种选用:

  1. 安装具备的<picture>元素或者将被请求的srcset属性。
  2. 安装单意气风发的low-res版本图片
  3. 设置单风姿洒脱的high-res版本图片

相比好的方案是2或3,因为只要把装有的图纸都给下载下来存着有一点浪费内部存款和储蓄器。

假若你将low-res版本在install的时候缓存了,然后在页面加载的时候你想要尝试从互连网上下载high-res的版本,不过即使high-res版本下载战败以来,就照样用low-res版本。这一个主张很好也值得去做,可是有三个标题:

即便我们有下边二种图片:

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" />

只要大家在二个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;" />

图片 11

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

动用 Service worker 创造多个特别轻巧的离线页面

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

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

让大家想像以下景况:我们那儿在大器晚成辆通往村庄的列车里,用移动设备望着豆蔻年华篇很棒的小说。与此同有时间,当您点击“查看更加的多”的链接时,轻轨忽地步入了隧道,引致移动器具失去了网络,而
web 页面会显示出相通以下的剧情:

图片 12

那是一定令人心寒的体会!幸运的是,web
开拓者们能因而一些新特色来改过这类的客商体验。小编近日直接在折腾 ServiceWorkers,它给 web 带给的数不尽恐怕性总能给自家惊奇。瑟维斯 Workers
的精髓特质之一是允许你检查评定互连网伏乞的风貌,并让您作出相应的响应。

在这里篇随笔里,小编策画用此本性检查客商的一时一刻网络连接情状,要是没连接则赶回贰个拔尖轻松的离线页面。就算这是贰个不行根底的案例,但它能给你带给启示,让您驾驭运转并运转该性子是多么的简要!要是你没领悟过
Service Worker,作者提出您看看此 Github
repo,理解越多相关的新闻。

在本案例早先前,让大家先简单地拜访它的做事流程:

  1. 在客户首次访问我们的页面时,大家会设置 ServiceWorker,并向浏览器的缓存增多大家的离线 HTML 页面
  2. 接下来,假若客户筹算导航到另贰个 web
    页面(同一个网站下),但此刻已断网,那么大家将重回已被缓存的离线
    HTML 页面
  3. 唯独,如若客户准备导航到别的一个 web
    页面,而这时互联网已接连,则能照常浏览页面

小结

PWA能力正被遍布集团及开垦者们关心,固然日前各器械的辅助合营有待拉长,但这一个都正在不断的精雕细刻发展。笔者也信赖在不久的将来,PWA技术会日渐广泛推广,为举不胜举公司和顾客带给便利。本文和我们齐声享受了PWA的相关本事与实例操作,前边还大概会就新闻推送、数据同步等作用做尤其索求沟通。借使我们在念书PWA的历程中遇见其余标题,招待一同谈谈沟通。

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": "48x48" }, { "src":
"/html/app-manifest/logo_96.png", "type": "image/png", "sizes": "96x96"
}, { "src": "/html/app-manifest/logo_192.png", "type": "image/png",
"sizes": "192x192" }, { "src": "/html/app-manifest/logo_512.png",
"type": "image/png", "sizes": "512x512" } ], "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": "48x48"
    },
    {
      "src": "/html/app-manifest/logo_96.png",
      "type": "image/png",
      "sizes": "96x96"
    },
    {
      "src": "/html/app-manifest/logo_192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "/html/app-manifest/logo_512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": "/?launcher=true",
  "display": "standalone",
  "background_color": "#287fc5",
  "theme_color": "#fff"
}

icon需求策画二种标准,最大要求512px *
512px的,那样Chrome会自动去筛选合适的图样。尽管把display改成standalone,从变化的Logo打开就能够像张开八个App形似,未有浏览器地址栏那多少个东西了。start_url内定展开之后的输入链接。

然后增添二个link标签指向那些manifest文件:

JavaScript

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

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

如此组合Service Worker缓存:
图片 13把start_url指向的页面用ServiceWorker缓存起来,这样当客商用Chrome浏览器张开那么些网页的时候,Chrome就能够在底部弹一个提醒,询问客商是还是不是把那一个网页加多到桌面,假诺点“增多”就能够生成三个桌面图标,从那么些Logo点进去就像张开叁个App同样。心得如下:

图片 14

正如为难的是Manifest这段时间唯有Chrome扶助,况兼只可以在安卓系统上利用,IOS的浏览器不可能加多二个桌面Logo,因为IOS未有开放这种API,不过笔者的Safari却又是足以的。

综上,本文介绍了怎么用Service Worker结合Manifest做一个PWA离线Web
APP,首假使用ServiceWorker调控缓存,由于是写JS,相比较灵敏,还是能与页面实行通信,别的通过央求页面包车型大巴翻新时间来判别是还是不是需求更新html缓存。ServiceWorker的宽容性不是特意好,但是前程相比较光明,浏览器都在预备援救。现阶段能够组合offline
cache的Manifest做离线应用。

有关阅读:

  1. 缘何要把网址晋级到HTTPS
  2. 怎么把网站晋级到http/2
  3. 自家是哪些让网址用上HTML5
    Manifest

1 赞 1 收藏
评论

图片 15

其次步:创立三个应用程序项目清单(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" :
"72x72", "type" : "image/png" }, { "src" : "/images/logo/logo152.png",
"sizes" : "152x152", "type" : "image/png" }, { "src" :
"/images/logo/logo192.png", "sizes" : "192x192", "type" : "image/png" },
{ "src" : "/images/logo/logo256.png", "sizes" : "256x256", "type" :
"image/png" }, { "src" : "/images/logo/logo512.png", "sizes" :
"512x512", "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"         : "72x72",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo152.png",
      "sizes"         : "152x152",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo192.png",
      "sizes"         : "192x192",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo256.png",
      "sizes"         : "256x256",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo512.png",
      "sizes"         : "512x512",
      "type"          : "image/png"
    }
  ]
}

程序清单文件构造建设完未来,你须要在各类页面上援引该文件:

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

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

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

  • name: 客商观察的使用名称
  • short_name: 应用短名称。当展现接纳名称的地点远远不够时,将选择该名称。
  • description: 动用描述。
  • start_url: 使用开首路线,相对路线,默感觉/。
  • scope: URL范围。举个例子:要是你将“/app/”设置为UENCOREL范围时,那几个动用就能够直接在这里个目录中。
  • 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: 二个富含全体图片的数组。该数组中各类成分包罗了图片的UENCOREL,大小和档期的顺序。

赢得赞助

假如你相逢麻烦,请在Stackoverflow上发帖询问,使用‘service-worker’标签,以便于大家马上跟进和不择手腕扶持您消除难点。

赞 2 收藏
评论

图片 15

有关我:刘健超-J.c

图片 17

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

图片 15

Service Worker

ServiceWorker是PWA的宗旨能力,它亦可为web应用提供离线缓存功用,当然不唯有如此,上边罗列了黄金时代部分ServiceWorker的表征:

据说HTTPS
意况,那是创设PWA的硬性前提。(LAMP境况网址升级HTTPS应用方案)

是一个单独的 worker 线程,独立于近来网页进度,有和睦单独的 worker
context

可阻拦HTTP央浼和响应,可缓存文件,缓存的文书能够在网络离线状态时取到

能向客商端推送新闻

不可能直接操作 DOM

异步完成,内部大都以通过 Promise 达成

转载本站文章请注明出处:vns威尼斯城官网登入 http://www.tiec-ccpittj.com/?p=4286

上一篇:

下一篇:

相关文章