更新 : 2019-06-29 css
自從 pwa 一推出開始玩了一把,一直到如今才真的有項目需求...html
從新整理了一下. git
https://angular.io/guide/service-worker-getting-startedgithub
跟着 get start 走,基本上 3 個 command 就搞定了. 真實方便呢web
下面提一提須要留意的東西 shell
Hash Mismatch 問題npm
若是咱們用 live server 來測試, 你會發現 pwa 跑不起來, api
若是咱們用 iis 也頗有可能出現這種狀況 app
其中的關鍵就是, ng build 的時候 angular 會拿 index.html 來 hash dom
而後以這個判斷內容是否有修改. 這個是很經常使用的技術. 好比 html content security policy 在保護 script 執行時也有對比 hash 的概念
live server 和 iis 或者 cdn 常常會幫咱們 minify html, 因此會生成的 hash 與 ng build 的時候不吻合 (ng build 的時候沒有 minify)
官方的例子很巧妙的使用了 http-server 避開了這件事兒... 也留些了坑 /.\
https://github.com/angular/angular/issues/21636 (不少人踩進去了...)
固然你也不能怪誰啦...
指望之後 angular 會幫咱們 minify 咯
https://github.com/angular/angular-cli/issues/11360
https://github.com/angular/angular/issues/23613
https://www.willpeavy.com/tools/minifier/
目前個人解決方法就是手動提早 minify index.html 才 ng build.
若是是開發階段,仍是用 http-server 吧.
npm i g http-server
http-server -p 4200 -a localhost ./dist/project-name -o http://localhost:4200/index.html
另外一個要注意的是 cache dataGroups 機制.
data groups 一般用來 cache api 返回的資料.
它有 2 個 mode
一個是 freshness, 另外一個是 performance
先說 performance,它就好像通常的 js 的 cache 同樣,有 cache 就不會去 server, 等到 max age 到爲止.
freshness 比較特別, 在 network 好的狀況下, 它老是去 server 拿回來,而後存一份 cache
當 offline 時它會立刻使用 cache, 或者時 network 超時的時候它會馬上返回 cache,
而後繼續等待 network 把資料拿回來後更新 cache, 注意它只是更新 cache 並不會通知 app 哦, 因此 app 這時候用的是以前 cache 的資料。
這個體驗就不是很好了,可是一個請求是沒法得到 2 個 response 的,若是拿了 cache 那麼就獲取不到新的了.
咱們也沒法精準的判斷 response 是 from cache or server. (最多隻能判斷 timeout 時間來猜想而已.)
通常上咱們的需求是, offline 用 cache, online 用 server. 沒有超不超時的概念.
因此我一般的作法時 set 一個很長的超時, 若是用戶不是 offline 而是超時的話也不會用 cache, 而是報錯之類的處理.
還有一個好的功能是, by pass
To bypass the service worker you can set ngsw-bypass as a request header, or as a query parameter. (The value of the header or query parameter is ignored and can be empty or omitted.)
在請求 header 加上 ngsw-bypass 就能夠 skip 掉 service worker 的 fetch 了.
最後在說說 notification click 的問題.
https://github.com/angular/angular/issues/20956
這個 issue 被關掉了, ng 提供了一個監聽的方法
this.swPush.notificationClicks.subscribe(v => { console.log('done'); });
這個只有在 app 打開着的狀態下才有用, ng 並無實現 action open window ...
若是咱們要實現依然須要修改 ngsw-worker.js
真的是啊....
https://github.com/angular/angular/issues/21197
也沒有給咱們好的方式去擴展
目前用到一個作法是 ..
https://medium.com/@smarth55/extending-the-angular-cli-service-worker-44bfc205894c
//my-service-worker.js self.addEventListener('notificationclick', (event) => { console.log('notification clicked!') }); //app.module.ts ServiceWorkerModule.register('my-service-worker.js', { enabled: environment.production }) "assets": { ..., "src/my-service-worker.js" } //my-service-worker.js importScripts('./ngsw-worker.js'); self.addEventListener('notificationclick', (event) => { console.log('notification clicked!') });
作法就是 extends + override 咯。這樣就能夠實現了咯
一個好得體驗應該是這樣子,到用戶在線時,咱們不該該發 notification,而應該用 web socket 去同步資料
只有當用戶不在線時,咱們才須要經過 notification... 否則你想,用戶就在屏幕前,notification 一直髮... 人家會不喜歡嘛。
PWA (Progressive Web Apps) 是將來網頁設計的方向. 漸進式網站.
Angular v5 開始支持 pwa 網站 (所謂支持意思是說有一些 build in 的方法和規範去實現它) 。
就目前來講 pwa 有幾個特色 :
1.https
2.Service work
3.Cache API
4.攔截 Fetch (任何遊覽器發出的請求, 包括 index.html)
5.Push API
6.Share API
主要的用途是 :
1. offline view (經過 service work + cache + 攔截 fetch 實現)
2. push notification (經過 service work + Push API + Notification API 實現)
3. AMP 網站預加載 service-work.js (在 amp page 出發 service worker 預加載整個頁面須要的 html,js.css)
參考 :
https://blog.angular-university.io/service-workers/
https://blog.angular-university.io/angular-service-worker/
實現我就不說了,人家已是 step by step 了. 我就講一些重點吧.
service work 比較複雜的地方是 life cycle.
當你訪問一個網站後 www.domain.com
當頁面渲染好後, ng 會找到一個好的時間點去 register service worker 也就是加載 "/ngsw-worker.js".
ng 有本身的方式(好比對比文件的 hash 等等)去管理 life cycle (若是你知道怎麼本身實現 service worker 的話,你會發現 ng 徹底本身控制了 life cycle 而沒有使用 default 的)
service work 開啓後, 就是通常的預加載 css, js, html 等等. 而後通通都會 cache 起來.
完成後, 你 offline 就能夠看到效果了. 你 refresh 的話會發現全部的請求都是從 cache 返回的,包括 index.html
連 index.html 都 cache 起來了,那要怎樣更新網站呢 ?
每一次更新, ng 在 cli build 的時候都會生產一個 hash 放進 ngsw-worker.js,
網站每一次刷新雖然會先使用 cache 版本,可是它也會立刻去加載 ngsw-worker.js 而後進行判斷看 hash 是否同樣。
若是發現有新的 js,css 那麼就會去加載,等到下一次 refresh 就會使用新版本了. 若是你但願用戶立刻使用新版本, ng 也開放了一個 API
能夠經過 subscribe 的方式監聽這個 update event, 而後能夠 alert 用戶叫用戶立刻 refresh.
因此流程是 cache first -> check update -> notify user and update now Or wait for user next refresh
我建議在網站比較穩定後才設置 service work, 而
並且網頁必須向後兼容, 或至少要有錯誤處理在版本太久的狀況下。
由於無論怎樣,用戶必定會先獲取到 cache 的版本,若是你的 cache 版本運行失敗(好比你的 Ajax response 已經換了, 而以前的 js 版本沒法處理, 甚至 error, 這樣用戶可能很是的難升級到新版本,並且體驗也會很糟. 因此要用 pwa 要注意這個哦)
除了 cache, ng 也封裝了 push notification。
以前寫過一篇關於 push 的原生實現.
http://www.cnblogs.com/keatkeat/p/7503615.html
ng 的實現看這個
https://medium.com/google-developer-experts/a-new-angular-service-worker-creating-automatic-progressive-web-apps-part-2-practice-3221471269a1
目前還不支持 notification click 時間,這個還蠻糟糕的,很是重要的功能丫。怎麼會沒有實現呢 ? https://github.com/angular/angular/issues/20956
並且也沒有擴展的方式,若是硬要就須要直接改 ngsw-worker.js 源碼了。
最後說說 App-shell
這個和 skeleton 相似的概念, 取代單調的 loading bar.
step by step : https://blog.angular-university.io/angular-app-shell/
ng 的實現手法是經過 cli build 時運行 server render, 而後把渲染好的 skeleton page 插入到 index.html.