PWA substitute surgery: ServiceWorker - caches

In PWA Disguise: manifest.json us through manifest.jsonto make the Web can generate a shortcut on the desktop, and does not need to hide the address bar at the time of execution, so that with the average App is no longer much difference in appearance, then we have to solve the Web App another big problem - off mechanism , although the current system is almost all done instantly through the Internet to exchange information with back-end, you can not say if a majority of the network, then App will probably lose its function, but with the web the difference is that the state still has no Internet screen, while the default web browser will display a warning screen, the more contrast unfriendly for the average user, the sky will be little better App Internet download information stored on the machine side, when off-line, although no longer do with the back-end data exchange, but can still provide information acquired before, although the Web also provides offline storage mechanism, but did not say deducted security, the development of is more difficult, especially user (or browser extension) can also prevent related functions.

ServiceWorker can run a scripting in the browser background, then we have to practice how to solve the problem when the network is offline Web App experience through caching mechanism ServiceWorker of ServiceWorker in the end is doing? I can say is that curtain glimpse of the wall to listen, sly .

operation flow

Because ServiceWorker can monitor any access to the front, they were required to be run under HTTPS, the only exception is the native side, in order to facilitate the development, localhostwill also be considered secure transmission browser, then we begin to gradually implement ServiceWorker .

We continue PWA steganography: manifest.json the program to as an example.
first-app_2017-09-25.zip

To download please remember to through instruction npm installto re-install the package.
We here through the ng build --prod -ohinstructions to compile, so that the output file name does not contain hash values.
-oh: --output-hashingAbbreviation.

References:
the MDN - Use Workers Service
Google Developers - Service Workers: AN Introduction

registered

First, we established in the project directory sw.jsas ServiceWorker script, and the establishment of a register_sw.jsresponsible for registering the script syntax is as follows:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('./sw.js')
    .then(reg => {
      // registration worked
      console.log('[Service Worker] Registration succeeded. Scope is ' + reg.scope);
    }).catch(error => {
      // registration failed
      console.log('[Service Worker] Registration failed with ' + error);
    });
}

We can see from Ready Is Serviceworker? Website support of various browsers.

Followed by Home ( index.htmladded to) register_sw.js.

<!doctype html>
<html lang="zh">
...
<body oncontextmenu="return false">
  <app-root></app-root>
  <script type="text/javascript" src="register_sw.js"></script>
</body>

</html>

We can also omit register_sw.jsfiles directly to the registered grammar written in the pages, but do not ServiceWorker script - sw.js(still blank) also moved within a page, because the browser will be run as a separate thread (Thread) in the background sw.js, so means ServiceWorker not intervene front-end web content .

Through Chrome Extensions - Web Server for Chrome to perform, you can see though sw.jsis blank, but ServiceWorker already running.

And manifest.jsonas we will register_sw.jsand sw.jsadded to .angular-cli.jsonthe assets, will be copied when this build.

Join Event

Open sw.jsand add three events: install(installation), activate(start), fetch(access), and through console.logto confirm whether an event is triggered.

self.addEventListener('install', event => {
  console.log('[ServiceWorker] Install');
});

self.addEventListener('activate', event => {
  event.waitUntil(clients.claim());
});

self.addEventListener('fetch', event => {
  console.log('[ServiceWorker] fetch', event.request);
});

Directly in the original browser window refresh, the browser can be found very clever script found ServiceWorker ( sw.js) has been changed, so the more a # 251 of serial number, but watch carefully you can find it in the state is waiting to be activated, the current version is still the start of the previous version, this is because
when the browser front end that runs a Web application, the default browser does not terminate the current script, the script will wait until the update is no longer needed ServiceWorker (eg closed the current browser window) will be updated with the new script.

Close the current browser window and then open a new window page, you can find the current start ServiceWork its serial number is # 251 , switch to the Console window can also see related events are triggered.

如果希望異動過的程式能夠立即更新,可以在 install 事件內透過 skipWaiting 方法來立即啟用。
大专栏  PWA 替身術:ServiceWorker - cachesJonny-Huang.github.io//images/angular/training/pwa/pwa_61.png" alt=""/>
參考資料:MDN - ServiceWorkerGlobalScope.skipWaiting()


由上圖也可以了解 ServiceWork 的處理順序為
install(安裝) => activate(啟動) => fetch(存取)
installactivate 只會觸發一次,fetch 則是只要前端對後台發出 request 就會觸發。

靜態快取

開啟腳本(srcsw.js),先建立檔案快取清單-filesToCache,並將要快取的檔案加入期內,接著在 install 事件內將快取清單加入至快取內。
接著在 fetch 事件內去透過 respondWith 方法來阻止瀏覽器使用預設存取模式,並比對快取是否有該 request 請求的資料,若有則直接從快取提取,否則就使用預設模式存取, 相關代碼如下:

const cacheVersion = 'v1';
const filesToCache = [
  '0.chunk.js',
  'favicon.ico',
  'index.html',
  'inline.bundle.js',
  'main.bundle.js',
  'polyfills.bundle.js',
  'register_sw.js',
  'styles.bundle.css',
  'vendor.bundle.js',
  'assets/images/android_048.png',
  'assets/images/android_057.png',
  'assets/images/android_072.png',
  'assets/images/android_076.png',
  'assets/images/android_096.png',
  'assets/images/android_114.png',
  'assets/images/android_120.png',
  'assets/images/android_144.png',
  'assets/images/android_152.png',
  'assets/images/android_167.png',
  'assets/images/android_180.png',
  'assets/images/android_192.png',
  'assets/images/android_512.png'
];

self.addEventListener('install', event => {
  console.log('[ServiceWorker] Install');
  event.waitUntil(
    caches.open(cacheVersion)
    .then(cache => {
      console.log('[ServiceWorker] Caching app shell');
      return cache.addAll(filesToCache);
    })
  );
});

self.addEventListener('activate', event => {
  console.log('[ServiceWorker] Activate');
});

self.addEventListener('fetch', event => {
  console.log('[ServiceWorker] fetch', event.request);
  event.respondWith(
    caches.match(event.request)
    .then(response => response || fetch(event.request))
  );
});

開啟瀏覽器 ServerWork 的離線(Offline)選項或者直接停用 Web Server,重新整理後可以發現網頁依然存在,基本的離線機制已經完成了。

快取版本

sw.js 內的最上方我們宣告了一個常數當作快取名稱
const cacheVersion = 'v1';
到目前為止我們只做到將資料加到快取內,但是我們可能會隨著功能的變更讓網站結構調整,當然快取清單也必然會配合修改,這時候就會發生快取可能會殘留舊有而不需要的資料,或者是快取累計的資料過於龐大,因此我們需要一個方式可以移除這些不必要的資料。

我們可以透過開發者工具來查看目前快取的資料。

在這邊我們以最簡單的方式來處理,當快取規則與以往不同時我們透過變更 cacheVersion 來產生全新的快取區域,並將就的快取直接刪除。
開啟腳本並在 activate 事件添加刪除快取的程式碼,並將快取版本(cacheVersion)改為 v2

const cacheVersion = 'v2';
const filesToCache = [
  ...
];
...
self.addEventListener('activate', event => {
  console.log('[ServiceWorker] Activate');
  event.waitUntil(
    caches.keys()
    .then(keyList => {
      return Promise.all(keyList.map(key => {
        if (key !== cacheVersion) {
          return caches.delete(key);
        }
      }));
    })
  );
});
...

重新執行,可以發現快取名稱已經變成 v2,而原本的 v1 已經被移除了。

API 快取

因為筆者目前沒有建立 WebAPI 環境,所以在此不做練習,但是我們可以參考 MDN 網站 使用 Service Workers 的範例,由範例程式碼可以看到它的作法與我們上面的方法類似,當快取內沒有相關資料時就改從網路去後台抓取,差別就在於它抓取資料後會先存入快取內,這樣下次就可以直接從快取提取資料。

目前的機制看起來與其說我們在建立快取,不如說更像在實作一個 Web App 專屬的代理伺服器(Proxy Server),最重要的是這種架構讓開發人員可以專注在連線模式的系統運作,完全不需要思考離線的問題
但是目前也衍生出一些問題:

  • Although some API parameters the same, but will return different content at different times, for example: latest news, announcements ... and so on, all this time to fetch data from the cache if it will give the user the illusion of not updated data so we need another mechanism, when there is back-end network to fetch information through the Internet, as if reading from offline to change the data cache.
  • We not only query requirements, as well as for information to add, modify, delete the problem, although there are still pictures can make offline by caching, but for data movement and also how to deal with?
  • Like Line, this initiative by the backend server push aside the message to the client mode most commonly used but also how to reach people on the Web?

These issues have a chance to do the follow-up discussion.

first-app_2017-09-26.zip

Guess you like

Origin www.cnblogs.com/liuzhongrong/p/11874904.html