天天看點

PWA(Progressive Web App)初探總結

【 PWA 】

        今天開始 Research 一個新的前端技術,PWA( 全稱:Progressive Web App )也就是說這是個漸進式的網頁應用程式。這個技術的呢是 Google 公司于2015 年提出的,2016 年 6 月才推廣的項目。針對這一項技術目前在國外似乎已經很流行了,目前應用這項技術最火熱的應用是在印度( 大家或許會疑惑為什麼是在印度最流行呢吧,下文中會告訴大家哦 ),既然 PWA 這項技術在國外已經非常的流行了,那麼在國内或許會不遠了( Angular 5 中新增的功能中,重點在于能夠更輕松的建構漸進式網絡應用程式,也就是 PWA 了。作為Google 和 mozilla 的産物,肯定會越來越重視啦 )我引用一下關于PWA技術的一篇最早的部落格文中的一句話吧: “ escaping tabs without losing our soul “( 翻譯一下哈:逃避頁籤而不丢失我們的靈魂 )。

        官網上給出 PWA 的宣傳是 : Reliable ( 可靠的 )、Fast( 快速的 )、Engaging( 可參與的 )( 官網:https://developers.google.com/web/progressive-web-apps/     ps:需要翻牆哦  )。簡單的說一下這三個特性:

                 Reliable : 為什麼他是可靠的呢,當使用者從手機主螢幕啟動時,不用考慮網絡的狀态是如何,都可以立刻加載出 PWA。

PWA(Progressive Web App)初探總結

                 Fast:這一點應該都很熟悉了吧,站在使用者的角度來考慮,如果一個網頁加載速度有點長的話,那麼我們會放棄浏覽該網站,是以 PWA 在這一點上做的很好,他的加載速度是很快的。

PWA(Progressive Web App)初探總結

                                                                                                                              Engaging : PWA 可以添加在使用者的主螢幕上,不用從應用商店進行下載下傳( 似乎省了下載下傳流量哦!)他們通過網絡應用程式 Manifest file 提供類似于 APP 的使用體驗( 在 Android 上可以設定全屏顯示哦,由于 Safari 支援度的問題,是以在 IOS 上并不可以 ),并且還能進行 ”推送通知” 。

PWA(Progressive Web App)初探總結

         這三個主特性似乎能解釋我在前言中所說的 ”在印度最流行“ 。小小的普及一下,根據2016年第三季度的 IDC統計資料顯示,印度的智能手機的出貨量達到了3億,同時也超過了美國,成為了全球第二大隻能手機市場。皮尤斯資料報告 2015 年曾統計過“全球智能手機擁有率”。印度隻有 17% 的人口用的是智能手機。雖然絕大部分人有手機用,但為非智能機,另有 22% 的人沒有手機。針對印度的移動網絡流量來說,網絡狀況是非常不佳的,根據16年的 GSMA 印度移動經濟報告顯示,網絡覆寫率為34.8% 。主要集中在城鎮,印度廣大的農村還處于網絡盲區,城鄉數字化鴻溝很大。在印度,2G/3G 最主流,且 2G 占比還遠高于 3G , 是以針對這種狀态來說,PWA 技術最适合不過了。 

        在我對 PWA 技術的研究中發現 PWA 其中有三個關鍵的技術:

                Service Worker( ps:就叫做服務工廠吧,文章最後一條 URL 是 SW 的全面進階,可以研究研究哦 )                                 Manifest (應用清單)

                Push Notification(推送通知)

        下面我一一介紹着三個關鍵的技術:

                Service Worker( 以下用SW來代替 ) :

                SW 是什麼呢?這個是離線緩存檔案。我們 PWA 技術使用的就是它!SW 是浏覽器在背景獨立于網頁運作的腳本,它打開了通向不需要網頁或使用者互動的功能的大門,因為使用了它,才會有的那個 Reliable 特性吧,SW 作用于 浏覽器于伺服器之間,相當于一個代理伺服器( 用一張圖來表示一下他的位置 )。                                                                   

PWA(Progressive Web App)初探總結

                為什麼會用到 SW 呢?原聲 App 擁有Web應用通常所不具備的富離線體驗,定時預設更新,消息推送等功能,而 SW 标準讓在 Web App 上擁有這些功能成為可能!                 跟 SW 相同的 API 還有 App Cache ,為什麼不使用它呢? App Cache 是有局限性的,比如說:它很容易得解決 single web page application ( 單頁面應用 )的問題,但是在多頁面應用上會很麻煩, SW 解決的這個 App Cache 的缺點!

         下面我簡單而詳細的說一下 SW :

              1、 浏覽器支援                                                  順便帶一句:目前隻能在 HTTPS 環境下才能使用SW,因為SW 的權利比較大,能夠直接截取和傳回使用者的請求,是以要考慮一下安全性問題。

PWA(Progressive Web App)初探總結

               2、事件機制                                                     

PWA(Progressive Web App)初探總結

               3、 功能                      SW的功能還是比較逆天的!                      

  • 背景資料的同步
  • 從其他域擷取資源請求
  • 接受計算密集型資料的更新,多頁面共享該資料
  • 用戶端編譯與依賴管理
  • 後端服務的hook機制
  • 根據URL模式,自定義模闆
  • 性能優化
  • 消息推送
  • 定時預設更新
  • 地理圍欄

                        4、 生命周期

PWA(Progressive Web App)初探總結

                                   Parsed ( 解析成功 ): 首次注冊 SW 時,浏覽器解決腳本并獲得入口點,如果解析成功,就可以通路到 SW 注冊對象,在這一點中我們需要在 HTML 頁面中添加一個判斷,判斷該浏覽器是否支援 SW 。                            Installing ( 正在安裝 ):SW 腳本解析完成之後,浏覽器會嘗試進行安裝,installing 中 install 事件被執行,如果其中有 event.waitUntil ( ) 方法,則 installing 事件會一直等到該方法中的 Promise 完成之後才會成功,如果 Promise 被拒絕,則安裝失敗,SW會進入 Redundant( 廢棄 )狀态。

                      Installed / Waiting (安裝成功/等待中):如果安裝成功,SW 将會進入這個狀态。

                      Activating ( 正在激活 ):處于 waiting 狀态的 SW 發生以下情況,将會進入 activating 狀态中:                                                                目前已無激活狀态的 worker 、 SW腳本中的 self.skipWaiting()方法被調用 ( ps: self 是 SW 中作用于全局的對象,這個方法根據英文翻譯過來也能明白什麼意思啦,跳過等待狀态 )、使用者已關閉 SW 作用域下的所有頁面,進而釋放了目前處于激活狀态的 worker、超出指定時間,進而釋放目前處于激活狀态的 worker 

                      Activated ( 激活成功 ):該狀态,其成功接收了 document 全面控制的激活态 worker 。

                      Redundant ( 廢棄 ):這個狀态的出現時有原因的,如果 installing 事件失敗或者 activating 事件失敗或者新的 SW 替換其成為激活态 worker 。installing 事件失敗和 activating 事件失敗的資訊我們可以在 Chrome 浏覽器的 DevTools 中檢視:                                                               ( ps:我這個是正常的狀态下的 ,錯誤的話會有 error 提示的 )                         

PWA(Progressive Web App)初探總結

              5、主要依賴

                    SW 作為現代浏覽器的進階特性,依賴于 fetch 、promise 、CacheStorage、Cache、等浏覽器的基礎能力, Cache 提供了 Request / Response 對象對的存儲機制。CacheStorage 則提供了存儲 Cache 對象的機制。

PWA(Progressive Web App)初探總結

            6、安全性問題

                 跨域請求支援:  SW 可以攔截它作用域内的所有請求,跨域資源也不例外,但是浏覽器預設對跨域資源發起的是 no-cors 請求,得到的 response 是 opaque 的, 是以會導緻我們無法判斷跨域請求是否成功,以便進行緩存,是以我們需要修改 fetch 請求頭部資訊,添加 mode:’cors’ 标記。

                ( 名詞解釋一下喽,這部分知識是關于 fetch API 的,想了解更多的同學,自行搜尋相關的知識哈 )                 no-cors:該模式允許來自 CDN 的腳本、其他域的圖檔和其他一些跨域資源,但是首先有個前提條件,就是請求的 method 隻能是 HEAD 、GET 、POST 。此外,如果 ServiceWorkers 攔截了這些請求,它不能随意添加或者修改除這些之外 Header 屬性。第三,JS 不能通路 Response 對象中的任何屬性,這確定了跨域時 ServiceWorkers 的安全和隐私資訊洩漏問題。                 opaque:Response 對象中 type 屬性的值 , 在 ‘no-cors’ 模式下請求了跨域資源,依靠服務端來做限制。

            分享給大家一個 SW 全面進階的博文:

        Manifest ( 應用清單 )

              Web App Manifest 是一個 W3C 規範,它定義了一個基于 JSON 的 List 。Manifest 在 PWA 中的作用有:                                       能夠将你浏覽的網頁添加到你的手機螢幕上                   在 Android 上能夠全屏啟動,不顯示位址欄 ( 由于 Iphone 手機的浏覽器是 Safari ,是以不支援哦)                   控制螢幕 橫屏 / 豎屏 展示                   定義啟動畫面                   可以設定你的應用啟動是從主螢幕啟動還是從 URL 啟動                   可以設定你添加螢幕上的應用程式圖示、名字、圖示大小

        Push Notification ( 消息通知 )

              Push 和 Notification 是兩個不同的功能,涉及到兩個 API 。

              Notification 是浏覽器發出的通知消息。                            Push 和 Notification 的關系,Push:伺服器端将更新的資訊傳遞給 SW ,Notification: SW 将更新的資訊推送給使用者。

        缺點:

              1、浏覽器的支援度問題,尤其是 Safari 浏覽器,這樣就會導緻我們在 IOS 系統手機上沒辦法體驗 PWA 。( 誰讓 ‘ 果果 ’ 不是開源的呢 )

              2、根據國情來看哈,目前 Native App 的使用使用者都已經習慣了,雖然會下載下傳一下,但是現在 WiFi 到處都是了,畢竟 WiFi 的普及太快了。讓使用者使用 PWA 來替代 Native App 短時間會不适應的。                            3、消息推送問題,PWA的消息推送走的是 GCM( FCM )通道。而國内 Google 是無法通路的。(隻能翻牆了,但是工信部已經禁止使用 VPN 了。) 

              總體來說:

                    Google 的技術在國内推進比較緩慢,是以 PWA 在國内的發展是有多困難吧。

【 Demo 】

           首先呢,我們用到有 Node 和 Ngrok 。Node 的使用以及安裝我就不說啦,作為一名前端開發工程師肯定會使用的啦。不會使用也米有關系啦,我們有度娘呢,Ngrok 的安裝以及使用我就直接共享一個URl吧:http://blog.csdn.net/tomcat_2014/article/details/68944066( ps:我就偷懶一下 )            對了,我使用的是 Mac 本(我司配的啦),是以我接下來的流程和截圖都是 Mac 本上的。                        我們先建立一個關于 PWA 的項目檔案夾,                                     進入檔案夾下我們準備一張 120x120的圖檔一張,作為我們的應用程式圖示。                 建立一個 index.html  檔案                 建立一個 index.css 檔案                 建立一個 manifest.json 檔案                 建立一個 sw.js 檔案                 利用終端,安裝一下 http-server 服務                 下面我們看一下每個檔案中的代碼是什麼吧:

                index.html        

PWA(Progressive Web App)初探總結

                         index.css                  

PWA(Progressive Web App)初探總結

                manifest.json                                          short_name: “ " 使用者主螢幕上的應用名字                     display : “standalone"  設定啟動樣式,讓您的網絡應用隐藏浏覽器的 URL 位址欄                     start_url : “/“ 設定啟動網址,如果不提供的話,預設是使用目前頁面                     theme_color : “ “  用來告知浏覽器用什麼顔色來為位址欄等 UI 元素着色                     background_color: “ ” 設定啟動頁面的背景顔色                     icons:””  就是添加到主螢幕之後的圖示

PWA(Progressive Web App)初探總結

                sw.js

                處理靜态緩存,首先定義需要緩存的路徑,以及需要緩存的靜态檔案的清單。                 借助 SW 注冊完成安裝 SW 時,抓取資源寫入緩存中。使用了一個方法那就是 self.skipWaiting( ) 這個方法我在前邊介紹的時候也說了,為了在頁面更新的過程當中,新的 SW 腳本能夠立刻激活和生效。

PWA(Progressive Web App)初探總結

                                  處理動态緩存,我們監聽 fetch 事件,在 caches 中去 match 事件的 request ,如果 response 不為空的話就傳回 response ,最後傳回 fetch 請求,在 fetch 事件中我們可以手動生成 response 傳回給頁面。                  更新靜态資源,緩存的資源會跟随着版本的更新會過期的,是以會根據緩存的字元串名稱清除舊緩存。在新安裝的 SW 中通過調用 self.clients.claim( ) 取得頁面的控制權,這樣之後打開頁面都會使用版本更新的緩存。舊的 SW 腳本不在控制着頁面之後會被停止,也就是會進入 Redundant 期。                   

PWA(Progressive Web App)初探總結

                以上截圖中最左側是我檔案下的清單喽,下面我們來運作一下,終端啟動 http-server 服務,我們以關閉緩存的方式進行啟動。

PWA(Progressive Web App)初探總結

                接下來我們使用 ngrok 這個工具,進行内網穿透。在上邊啟動 http-server 服務的時候我們使用預設的端口号 8080 。是以我們在 ngrok 中我們綁定 端口 8080 。輸入指令 : ./ngrok http 8080 之後我們看一下。(記得再打開一個終端哦,在另一個終端中進行操作)

PWA(Progressive Web App)初探總結

                我們看到綠色的字母 online 表示内網穿透成功了,我們看最後一個 Forwarding     https:// 的,因為我們在上邊介紹了,SW 的權利比較大,為了保證資訊的安全性,我們使用 https 協定來進行通路。我們把它複制下來在 chrom 浏覽器中打開,-> 符号後邊的就不用複制了哈。( 每個人的 ‘隧道’ 都是不一樣的哦,這一點同學們可以在 ngrok 官網中進行查詢哦 )。                  我們打開 chrom 的調試工具,打開 application ,點選 service workers 之後我們會發現 sw.js 腳本已經存到了 SW 中 。

PWA(Progressive Web App)初探總結

                我們打開 Network 重新整理頁面一下,看看,我們的頁面資源來自 SW 而不是其他的地方,在 Console 中也列印出了我們在 index.html 中判斷的語句,浏覽器支援就會列印出這一句話哦。

PWA(Progressive Web App)初探總結

                接下來我們斷網操作,在 Application 中給 Offline 打上對勾就行啦。然後重新整理頁面,我們仍然能看到之前的頁面,原因就是我們在上圖看到,他的資源是從 SW 上獲得到的。當我們第一次打開這個頁面的時候,Resopnse 對象被存到了 Cache Storage ( 定義在 SW 規範中 ,相關資料請同學們自行查詢啦 )中,我們看下圖:

PWA(Progressive Web App)初探總結

                                 通過存放到 Cache Storage 中,我們下次通路的時候如果是弱網或者斷網的情況下,就可以不走網絡請求,而直接就能将本地緩存的内容展示給使用者,優化使用者的弱網及斷網體驗。

                這個時候肯定會有同學在想,如果内容更新了,那麼頁面展示的内容是新内容呢還是舊内容呢?下面我們操作一下,打開 index.html 檔案,我們在 body 中添加一個 p 标簽 ,然後回到頁面重新整理。

PWA(Progressive Web App)初探總結
PWA(Progressive Web App)初探總結

                我們看到,頁面上的内容并沒有顯示出我剛剛添加的那個 p 标簽。這說明了,我們拿到的資料還是從 Cache Storage 中擷取到的,Cache Storage中的内容并沒有更新,那麼我們怎麼才能讓我剛剛添加的那個 p 标簽顯示出來呢。                 我們打開 sw.js 腳本檔案,我們修改一下 cacheStorageKey。

PWA(Progressive Web App)初探總結

                                 我們關閉一下浏覽器,然後再次打開該網址,頁面出現了我們剛剛添加的那個 p 标簽。我們再看一下 Cache Storage 中的緩存名字,已經被修改。

PWA(Progressive Web App)初探總結

【 總結 】                  總結一下吧,在研究這個 PWA 的過程中,搜尋了相關的一大部分知識,就怕自己的腦洞不夠大。感覺 PWA 涉及到的 API 比較多。要想研究透徹 PWA 還需要研究它所涉及到的 API ,慢慢研究吧。npm 中已經有這個包了哦。想真實的對 PWA 做深入研究的同學,可以應用到實際項目中。( 我感覺,會有很多坑 ),不過呢,作為一名前端開發工程師,對于這種技術研究來說,當然是有坑就補,沒坑挖坑補。我會在接下來的日子中,抽出時間對 PWA 進行深入研究的。當然也會共享給大家。

        上文中如果有說錯的,或者錯誤的,歡迎各位大神指出!可以直接加我 QQ :568815707 ,說明意圖哦,不然會拒絕的。

參考URL( 有的是需要翻牆的哦 ):

                https://developers.google.com/web/progressive-web-apps/                 http://foio.github.io/service-worker-cache/                 http://bubkoo.com/2015/05/08/introduction-to-fetch/                 http://www.dongcoder.com/detail-437618.html                 http://imweb.io/topic/56592b8a823633e31839fc01                 https://75team.com/post/lifecycle.html                 https://segmentfault.com/a/1190000006061528                 https://www.w3ctech.com/topic/866                 http://dongcoder.com/detail-397355.html                 https://www.npmjs.com/package/web-pwa                 https://www.villainhr.com/tag/SW

繼續閱讀