引用
《瀏覽器工作原理與實踐》
PWA,全稱是 Progressive Web App ,翻譯過來就是漸進式網頁應用。根據字面意思,它就是“漸進式 +Web 應用”。對于 Web 應用很好理解了,就是目前普通的 Web 頁面,所以 PWA 所支持的首先是一個 Web 頁面。至于“漸進式”,就需要從下面兩個方面來理解。
- 站在 Web 應用開發者來說,PWA 提供了一個漸進式的過渡方案,讓普通站點逐步過渡到 Web 應用。采取漸進式可以降低站點改造的代價,使得站點逐步支持各項新技術,而不是一步到位。
- 站在技術角度來說,PWA 技術也是一個漸進式的演化過程,在技術層面會一點點演進,比如逐漸提供更好的設備特性支持,不斷優化更加流暢的動畫效果,不斷讓頁面的加載速度變得更快,不斷實現本地應用的特性。
從這兩點可以看出來,PWA 采取的是非常一個緩和的漸進式策略,不再像以前那樣激進,動不動就是取代本地 App、取代小程序。與之相反,而是要充分發揮 Web 的優勢,漸進式地縮短和本地應用或者小程序的距離。
那么 Web 最大的優勢是什么呢?我認為是自由開放,也正是因為自由和開放,所以大家就很容易對同一件事情達成共識,達成共識之后,一套代碼就可以運行在各種設備之上了,這就是跨平臺,這也恰恰是本地應用所不具備的。而對于小程序,倒是可以實現跨平臺,但要讓各家達成共識,目前來看,似乎還是非常不切實際的。
所以我給 PWA 的定義就是:它是一套理念,漸進式增強 Web 的優勢,并通過技術手段漸進式縮短和本地應用或者小程序的距離
。基于這套理念之下的技術都可以歸類到 PWA。
那今天就主要來聊聊 PWA 主要采用了哪些技術手段來縮短它和本地應用或者小程序的距離。
一、Web 應用 VS 本地應用
那相對于本地應用,Web 頁面到底缺少了什么?
- 首先,Web 應用
缺少離線使用能力
,在離線或者在弱網環境下基本上是無法使用的。而用戶需要的是沉浸式的體驗,在離線或者弱網環境下能夠流暢地使用是用戶對一個應用的基本要求。 - 其次,Web 應用還
缺少消息推送的能力
,因為作為一個 App 廠商,需要有將消息送達到應用的能力。 - 最后,Web 應用
缺少一級入口
,也就是將 Web 應用安裝到桌面,在需要的時候直接從桌面打開 Web 應用,而不是每次都需要通過瀏覽器來打開。
針對以上 Web 缺陷,PWA 提出了兩種解決方案:通過引入 Service Worker 來試著解決離線存儲和消息推送的問題,通過引入 manifest.json 來解決一級入口的問題。下面就來詳細分析下 Service Worker 是如何工作的。
二、什么是 Service Worker
先來看看 Service Worker 是怎么解決離線存儲和消息推送的問題。
其實在 Service Worker 之前,WHATWG 小組就推出過用 App Cache 標準來緩存頁面,不過在使用過程中 App Cache 所暴露的問題比較多,遭到多方吐槽,所以這個標準最終也只能被廢棄了,可見一個成功的標準是需要經歷實踐考量的。
所以在 2014 年的時候,標準委員會就提出了 Service Worker 的概念,它的主要思想是在頁面和網絡之間增加一個攔截器,用來緩存和攔截請求。整體結構如下圖所示:
在沒有安裝 Service Worker 之前,WebApp 都是直接通過網絡模塊來請求資源的。安裝了 Service Worker 模塊之后,WebApp 請求資源時,會先通過 Service Worker,讓它判斷是返回 Service Worker 緩存的資源還是重新去網絡請求資源。一切的控制權都交由 Service Worker 來處理。
三、Service Worker 的設計思路
現在知道 Service Worker 的主要功能就是攔截請求和緩存資源,接下來就從 Web 應用的需求角度來看看 Service Worker 的設計思路。
1. 架構
通過前面頁面循環系統的分析,我們已經知道了 JavaScript 和頁面渲染流水線的任務都是在頁面主線程上執行的,如果一段 JavaScript 執行時間過久,那么就會阻塞主線程,使得渲染一幀的時間變長,從而讓用戶產生卡頓的感覺,這對用戶來說體驗是非常不好的。
為了避免 JavaScript 過多占用頁面主線程時長的情況,瀏覽器實現了 Web Worker
的功能。Web Worker 的目的是讓 JavaScript 能夠運行在頁面主線程之外,不過由于 Web Worker 中是沒有當前頁面的 DOM 環境的,所以在 Web Worker 中只能執行一些和 DOM 無關的 JavaScript 腳本,并通過 postMessage
方法將執行的結果返回給主線程。所以說在 Chrome 中, Web Worker 其實就是在渲染進程中開啟的一個新線程,它的生命周期是和頁面關聯的。
“讓其運行在主線程之外
”就是 Service Worker 來自 Web Worker 的一個核心思想。不過 Web Worker 是臨時的,每次 JavaScript 腳本執行完成之后都會退出,執行結果也不能保存下來,如果下次還有同樣的操作,就還得重新來一遍。所以 Service Worker 需要在 Web Worker 的基礎之上加上儲存功能
。
另外,由于 Service Worker 還需要會為多個頁面提供服務,所以還不能把 Service Worker 和單個頁面綁定起來
。在目前的 Chrome 架構中,Service Worker 是運行在瀏覽器進程中的,因為瀏覽器進程生命周期是最長的,所以在瀏覽器的生命周期內,能夠為所有的頁面提供服務。
2. 消息推送
消息推送也是基于 Service Worker 來實現的。因為消息推送時,瀏覽器頁面也許并沒有啟動,這時就需要 Service Worker 來接收服務器推送的消息,并將消息通過一定方式展示給用戶。關于消息推送的細節這里就不詳述了,如果你感興趣的話可以自行搜索相關資料去學習。
3. 安全
基于 Web 應用的業務越來越多了,其安全問題是不可忽視的,所以在設計 Service Worker 之初,安全問題就被提上了日程。
關于安全,其中最為核心的一條就是 HTTP。知道,HTTP 采用的是明文傳輸信息,存在被竊聽、被篡改和被劫持的風險,在項目中使用 HTTP 來傳輸數據無疑是“裸奔”。所以在設計之初,就考慮對 Service Worker 采用 HTTPS 協議,因為采用 HTTPS 的通信數據都是經過加密的,即便攔截了數據,也無法破解數據內容,而且 HTTPS 還有校驗機制,通信雙方很容易知道數據是否被篡改。關于 HTTPS 協議,會在最后的安全模塊詳細介紹。
所以要使站點支持 Service Worker,首先必要的一步就是要將站點升級到 HTTPS。
除了必須要使用 HTTPS,Service Worker 還需要同時支持 Web 頁面默認的安全策略、儲入同源策略、內容安全策略(CSP)等,關于這些,后續也會詳細介紹。
四、 總結
先分析了 PWA,它是由很多技術組成的一個理念,其核心思想是漸進式。對于開發者,它提供了非常溫和的方式,讓開發者將普通的站點逐步過渡到 Web 應用。對于技術本身而言,它是漸進式演進,逐漸將 Web 技術發揮到極致的同時,也逐漸縮小和本地應用的差距。在此基礎上,又分析了 PWA 中的 Service Worker 的設計思路。
另外,PWA 還提供了 manifest.json 配置文件,可以讓開發者自定義桌面的圖標、顯示名稱、啟動方式等信息,還可以設置啟動畫面、頁面主題顏色等信息。關于 manifest.json 的配置還是比較簡單的,詳細使用教程網上有很多,這里我就不做介紹了。
添加桌面標、增加離線緩存、增加消息推送等功能是 PWA 走向設備的必備功能,但我認為真正決定 PWA 能否崛起的還是底層技術,比如頁面渲染效率、對系統設備的支持程度、WebAssembly 等,而這些技術也在漸進式進化過程中。所以未來如何,拭目以待