Posted on Leave a comment

[技術支援-3] Service worker離線支援

關於Service worker

Angular在第5版新推出了支援Service worker的功能,主要是可以讓Angular更能符合PWA的概念

所謂PWA(Progressive Web App)是希望能夠讓Web application盡可能的在各種環境(網路環境、手機作業系統等)下都能順暢且不減功能性的運作。
例如要可以支援離線功能,在使用 App 收信、寫信、刪除信件等動作,都需要將結果丟回伺服器儲存,但在某些環境下並無法一直使用網路連線,因此必須使用一種機制,讓我們仍能順暢的使用這些功能,待網路正常連線,再將剛才所執行的一切動作反應回伺服器
而Service Worker可以讓Web application做到上面這樣的事情。

使用Service worker所需環境

要使用Angular Service worker,您必須具有以下Angular和CLI版本:

  • Angular 5.0.0或更高版本。
  • Angular CLI 1.6.0或更高版本。

Web application必須在支援Service worker的Web瀏覽器中運行。
目前支持最新版本的Chrome和Firefox。其他瀏覽器的支援狀況如下圖(連結):

Service Worker 的生命週期

圖片來源:Browser push notifications using JavaScript

在創建新的應用程序時使用Service worker

--service-worker標誌添加到ng new命令中:
ng new my-project –service-worker

在現有的應用程序加入Service worker

  • 步驟1:添加service worker package
    yarn add @angular/service-worker
  • 步驟2:在CLI中啟用service worker
    ng set apps.0.serviceWorker=true
  • 步驟3:導入並註冊service worker
    src/app/app.module.ts

    import { ServiceWorkerModule } from '@angular/service-worker';
    import { environment } from '../environments/environment';

    app.module.ts

    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        ServiceWorkerModule.register('/ngsw-worker.js', {enabled: environment.production})//註冊ServiceWorker腳本的名稱
      ],
      providers: [
        CheckForUpdateService,
        LogUpdateService,
        PromptUpdateService,
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
  • 步驟4:創建配置文件ngsw-config.json
    大多數src/ngsw-config.json合理的默認值如下:
    {
    “index”: “/index.html”,
    “assetGroups”: [{
    “name”: “app”,
    “installMode”: “prefetch”,
    “resources”: {
    “files”: [
    “/favicon.ico”,
    “/index.html”
    ],
    “versionedFiles”: [
    “/*.bundle.css”,
    “/*.bundle.js”,
    “/*.chunk.js”
    ]
    }
    }, {
    “name”: “assets”,
    “installMode”: “lazy”,
    “updateMode”: “prefetch”,
    “resources”: {
    “files”: [
    “/assets/**”
    ]
    }
    }]
    }
  • 第5步:構建項目
    ng build –prod

觀察Service worker的運行

可以使用Chrome Debug Tool,設置瀏覽器狀態為離線

從Network的資料會可以看到現在HTTP資料的來源是來自於service worker

這個面版可以觀察Service worker的運行狀況

SwUpdate service

下面是利用SwUpdate來取得現有可用及被啟用的notified的方式

@Injectable()
export class LogUpdateService {

  constructor(updates: SwUpdate) {
    updates.available.subscribe(event => {
      console.log('current version is', event.current);
      console.log('available version is', event.available);
    });
    updates.activated.subscribe(event => {
      console.log('old version was', event.previous);
      console.log('new version is', event.current);
    });
  }
}

檢查更新的方式

import { interval } from 'rxjs/observable/interval';

@Injectable()
export class CheckForUpdateService {

  constructor(updates: SwUpdate) {
    interval(6 * 60 * 60).subscribe(() => updates.checkForUpdate());
  }
}

強制更新資料

@Injectable()
export class PromptUpdateService {

  constructor(updates: SwUpdate) {
    updates.available.subscribe(event => {
      if (promptUser(event)) {
        updates.activateUpdate().then(() => document.location.reload());
      }
    });
  }
}

Service worker和快取緩存離線資料

我們可以將Service worker想像成像瀏覽器快取或者CDN edge一樣,都是會將網頁資料暫存起來。只是Service worker是將資料存在瀏覽器上。

透過設置src/ngsw-config.json來設定版本資訊,被分組到同一個版本的文件通常包括HTML,JS和CSS,這些文件的完整性非常重要,因為JS和CSS常常會互相引用並彼此依賴。
例如在index.html裡可能引用了bundle.js並呼叫了它的方法startApp(),如果某次改版我們將startApp()改名為runApp(),但是在index.html裡若是舊的版本,依舊呼叫startApp(),就會造成執行上的錯誤。

因此快取設定資料的完整性和版本的一致性非常的重要,可以確保ANGULAR在離線執行時可以正常運作。

每次使用者打開或更新網頁時,Angular service worker都會透過ngsw.json的更新來檢查應用程序的更新。如果有發現有更新的頁面,將會自動下載並緩存,在下次載入網頁時提供。

Debugging the Angular service worker

有關於service worker的debug資訊都在ngsw/底下,公開的網址為ngsw/state

下面是一個ngsw/state的範例:

NGSW Debug Info:
//這邊是指service worker的Driver狀態,有三種值:NORMAL(正常),EXISTING_CLIENTS_ONLY(舊的快取可安全使用),SAFE_MODE(版存資料失效,所有資料都會由網路提供)
Driver state: NORMAL ((nominal))
//最新清單的SHA hash
Latest manifest hash: eea7f5f464f90789b621170af5a569d6be077e5c
//上次更新檢查
Last update check: never
//版本資訊
=== Version eea7f5f464f90789b621170af5a569d6be077e5c ===

Clients: 7b79a015-69af-4d3d-9ae6-95ba90c79486, 5bc08295-aaf2-42f3-a4cc-9e4ef9100f65
//空閒任務隊列
=== Idle Task Queue ===
Last update tick: 1s496u
Last update run: never
Task queue:
 * init post-load (update, cleanup)
//調試日誌
Debug log:

配置文件格式介紹

詳細說明請見Service Worker Configuration

參考資料

Leave a Reply