關於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