作者 | 彭星
編輯 | 尾尾
一、回顧歷史:移動時代之初,Web遭遇兩大枷鎖
Web 在移動時代遭遇兩大枷鎖1.Web 在移動時代遭遇兩大枷鎖
當 Web 自信滿滿,步入移動時代之時,它還沒有做好充足的準備。
回顧 2014 到 2015 年那段時間,作為前端開發人員,我正忙著前后端分離和體驗優化。那時,我投入精力最多的就是移動站點的體驗優化,例如提升首屏速度,提升動畫流暢性等。為了達到更好的優化效果,我心力憔悴,HTTP 緩存、HTTP2 等一些優化技術都用上了,但體驗依然比 Native App 差很多,始終無法突破移動設備上瀏覽器(和 WebView) 給 Web 帶來的 用戶體驗枷鎖。
除開 Web App 的體驗問題,還有一個很重要的問題制約著 Web 在移動時代的發展,那就是第二個枷鎖——用戶留存枷鎖。Native App 在安裝完成之后會在桌面上有一個入口,后續用戶觸達 App 只有一步,而 Web App 在移動時代最主要的入口還是搜索引擎,用戶從瀏覽器到站點需要經過搜索引擎,還需要記住和輸入上次搜索的內容。當然,用戶還可以直接輸入站點 URL 地址,但這對于移動用戶來說,無疑成本巨大,這就導致用戶和 Web 站點之間的粘性非常脆弱。
兩大枷鎖禁錮了 Web 在移動端的發展,雖然移動 Web 可以觸達的用戶是 App 的三倍之多,但用戶的留存時間卻明顯少于在 App 上的留存時間,參考 What is Progressive web App (and Why Should You Care):
https://codeburst.io/what-is-progressive-web-app-and-why-should-you-care-e397e24b1257
對比下來,互聯網公司更愿意投入人力在 Native App 的開發上,而忽略 Web。因此,Native App 順勢迅速成長起來,大量的需求出現了,也吸引了各類培訓機構開啟相關 NA 開發的課程,吸引了很多人轉做 NA 開發,各種 Native App 的技術、教程、實踐等,也如雨后春筍般布滿了各大技術論壇。
2. 打造解開枷鎖的鑰匙
對于前期的失利,Web 顯然是不甘心的。想要繼續前進,就必須打造解開枷鎖的鑰匙——Progressive Web App( PWA ) 以及支撐 PWA 的一系列關鍵技術應運而生。
早在 2014 年, W3C 公布就公布過 Service Worker 的相關草案,但是其在生產環境被 Chrome 支持是在 2015 年。因此,如果我們把 PWA 的關鍵技術之一 Service Worker 的出現作為 PWA 的誕生時間,那就應該是 2015 年。
自 2015 年以來,PWA 相關的技術不斷升級優化,在用戶體驗和用戶留存兩方面都提供了非常好的解決方案。PWA 可以將 Web 和 App 各自的優勢融合在一起:漸進式、可響應、可離線、實現類似 App 的交互、即時更新、安全、可以被搜索引擎檢索、可推送、可安裝、可鏈接。
其中,App Manifest 讓 Web 站點能被添加到手機桌面,解決了用戶到達站點鏈條太長的問題;Service Worker 讓 Web 站點能夠離線狀態下正常使用,還有能讓用戶離線接受站點消息推送的 Web Push,這兩點非常值得關注。
3. 解開枷鎖,劍指NA痛點
而與此同時,如火如荼的 Native App 卻沒能很好地彌補自己的劣勢。
對于 Native App 來說,其 最大的痛點是由于其天生封閉的基因,內容無法被索引,這會導致后續一系列的問題。例如,用戶想知道紅燒肉的做法,還需要先知道 App 的名字,下載 App 后才能獲取內容,這個流程是十分不合理的。而隨著移動互聯網的發展,用戶下載 App 的熱情也逐漸減弱,再加上用戶 80% 的時間被 Top3 的超級 App 占據,對于站點來說,應用分發成本也因此越來越高了。
相對于 Native App 的封閉,PWA 卻是完全開放的——PWA 現有的所有技術都是遵循 W3C 的標準,完全開放,因此能夠快速被站點接受、被瀏覽器快速支持。
值得一提的是,為了解開傳統 Web 的兩個枷鎖,除 PWA 之外,業界也誕生了很多技術方案,例如部分廠商推出的小程序技術。
二、細解PWA:是否能真正彌補 Web 劣勢?
PWA 不是特指某一項技術,而是應用了多項技術的 Web App。其核心技術包括 App Manifest、Service Worker、Web Push、Credential Management API ,等等。其核心目標就是提升 Web App 的性能,改善 Web App 的用戶體驗。
下面我們詳細地看一下這些核心技術,是否能夠真正彌補 Web 劣勢。
1. Web App Manifest
Web App Manifest 是為了解決用戶留存問題而誕生的,它是一個外鏈的 JSON 文件,在這個文件中,像瀏覽器暴露了站點的名稱,地址,圖標等等元數據,可以看下面這個例子。Web App Manifest 有很多配置項,MDN 的文檔:
https://developer.mozilla.org/en-US/docs/Web/Manifest
{"name": "百度天氣","short_name": "天氣","icons": [{"src": "/dist/static/img/icons/android-chrome-192x192.png","sizes": "192x192","type": "image/png"}],"start_url": "/?from=homescreen","background_color": "#3E4EB8","display": "standalone","theme_color": "#2F3BA2"
}
在瀏覽器中通過 引入這個 JSON 文件,瀏覽器識別到這個文件的存在,會根據自己的機制決定是否彈出添加到桌面對話框,并在桌面上生成一個應用的圖標,通過點擊桌面圖標進入應用具有沉浸式的體驗,全屏顯示,沒有瀏覽器地址欄,并且還會自動添加應用啟動畫面,入下圖所示。
圖片來源于《下一代 Web 應用模型 — Progressive Web App》:
https://huangxuan.me/2017/02/09/nextgen-web-pwa/
Web App Manifest 當前也存在一些問題,比如 Web App Manifest 添加到桌面依賴于手機操作系統是否給瀏覽器開通在桌面創建快捷方式的權限,目前在國內,大部分情況下,瀏覽器的這個權限被默認禁止,需要用戶手動開啟,拿小米手機為例,可以進入設置 -> 更多應用 -> 找到對應的瀏覽器 -> 權限管理 -> 桌面快捷方式 -> 允許,對于大部分用戶來說,這個操作可能過于復雜了,這也是 PWA 添加到桌面在國內還沒有被廣泛接受的主要原因,很多廠商,包括百度在內,都在盡力推動手機廠商開啟這個權限。
其他 Web App Manifest 的詳細資料可以參考 LAVAS 官網中 Web App Manifest 的文檔:
https://lavas.baidu.com/doc/engage-retain-users/introduction
2. Service Worker
PWA 之所以能離線,是 Service Worker 的功勞。這并不是 W3C 第一次嘗試讓 Web 站點離線,在 Service Worker 之前,有個東西叫 Application Cache,,是不是很熟悉?但是,由于Application Cache 存在很多無法容忍和無法解決的問題(可以查看這篇博客 Application Cache is a Douchebag:https://alistapart.com/article/application-cache-is-a-douchebag),它在 HTML5.1 版本中被移出了。
現在,我們終于有一個沒有那么多問題的離線方案了,那就是 Service Worker。
Service Worker 是一個特殊的 Web Worker,獨立于頁面主線程運行,它能夠攔截和處理網絡請求,并且配合 Cache Storage API,開發者可以自由的對頁面發送的 HTTP 請求進行管理,這就是為什么 Service Worker 能讓 Web 站點離線的原因。
Service Worker 的工作流程如下圖所示。
Service Worker 的工作方式也衍生出了幾種不同的請求控制策略,networkFirst, cacheFirst, networkOnly, cacheOnly 和 fastest,對于不同類型的請求,我們應該采取不同的策略,靜態文件,我們可以選擇 cacheFirst 或者 fastest,甚至 cacheOnly,對于依賴后端數據的 AJAX 請求,我們應該選擇 networkFirst 或者 networkOnly,保證數據的實時性。
Service Worker 從在瀏覽器注冊到進入工作狀態和最終銷毀會經歷不同的階段,下圖比較清楚的畫出了 Service Worker 的生命周期。
在整個生命周期中,Service Worker 會拋出不同的事件,如 install, active, fetch 等,可以通過 self.addEventListener 來監聽。
比如,監聽網絡請求事件,這里我們采用的策略是 cacheFirst。
// service-worker.js
self.addEventListenr('fetch', (e) => {e.respondWith(caches.match(e.request).then((response) => {return response || fetch(e.request);}));
});
這里只是簡單的介紹了一下 Service Worker,詳細的使用文檔可以參考 怎么使用 Service Worker。
Service Worker 它并不只是能夠緩存離線文件,后臺同步和 Web Push 都是依賴于 Service Worker 工作的,因此它的重要性不言而喻。
3. Push Notification
Push Notification 其實是兩個 API 的結合, Notification API 和 Push API 。
Notification API 提供了開發者可以給用戶發送通知的能力,包括申請顯示通知權限,發起通知,以及定制通知的類型等等。Notification API 的歷史比較早,最早可以追溯到 2010 年,2011 年納入標準,時至今日,Notication API 已經獲得了大多數平臺的支持,包括 Chrome, Edge, Firefox, Safari 等的支持,比較可惜的是,iOS Safari 至今還不支持。
Push API,則是讓服務器能夠向用戶發送離線消息,即使用戶當前并沒有打開你的頁面,甚至沒有打開瀏覽器。瀏覽器在接到消息推送時,會喚醒對應的 Service Worker,并拋出 push 事件,開發者接收到事件之后調用 Notification API 彈出通知,這就完成了整個接受和展示的流程。
// service-worker.js
self.addEventListener('push', event => {event.waitUntil(// Process the event and display a notification.self.registration.showNotification("Hey!"));
});self.addEventListener('notificationclick', event => {// Do something with the eventevent.notification.close();
});self.addEventListener('notificationclose', event => {// Do something with the event
});
在之前的分享和文章中,很少提及 Web Push,這并不是因為它不重要,而是因為它在國內被支持程度非常低,支持 Web Push 的成本比 App Manifest 或者 Service Worker 要高的多,它需要瀏覽器廠商提供消息推送服務,截止到本文截稿,國內只有 UC 即將發布的 U2 內核的瀏覽器才支持 Web Push API,Chrome 也因為其依賴的 FCM/GCM 無法訪問而導致 Web Push 無法使用。
瀏覽器接收到離線消息需要完成兩個過程:
1、瀏覽器訂閱通知
2、服務器發送通知
瀏覽器訂閱通知,是指開發者調用 API 在消息服務器注冊,具體過程如下圖所示,通過服務器提供的 Public Key 從瀏覽器獲取 PushSubscription 對象,PushSubcription 包含瀏覽器對應的消息服務器的地址和一些密鑰認證數據,將它發送到服務器,服務器將這些數據存儲,發送離線消息需要使用到這些數據。訂閱通知的過程就完成了。
服務器發送通知,服務器用 Private Key 將消息加密發送到之前保存的 PushSubcription 中對應的消息服務器,消息服務器解密消息后將消息推送到用戶的瀏覽器,瀏覽器喚醒 Service Worker,這就完成了整個消息推送的過程。
除了 Web App Manifest、Service Worker、Push API 這三個關鍵的技術外,PWA 還包含很多優化的準則,比如 PRPL 模式,App Shell 模型,Credential Management API ,等等。PWA 不是某一種特定的技術,換句話來說,PWA 是采用各種技術達到站點用戶體驗非常好的 Web App。單單從技術上講,已經能夠很好地彌補傳統 Web 的劣勢了。
三、放眼未來:PWA 將帶來新一輪前端技術洗牌?
1. 業界廠商紛紛支持,包括蘋果
各家瀏覽器廠商在 2017 年開始大力支持 PWA,下圖統計了主流瀏覽器對 PWA 的支持程度,可以看到,大部分瀏覽器對 PWA 已經支持得很好了。
圖片來源于 ispwaready
UC 瀏覽器開發的 U2 內核已經支持 Push API 了,也是國內第一個支持 Push API 的瀏覽器。現在瀏覽器廠商唯恐自己沒跟上標準,而被淘汰。
不僅國內瀏覽器廠商的態度發生轉變,連蘋果都已經在幾個月前悄悄的進行了 Service Worker 的開發了,相信在不遠的將來,iOS 也將支持 PWA。
2. PWA 開發門檻也在降低
為了降低 PWA 的開發門檻,業界也推出了相應的工具。
例如,百度推出的 Lavas 就是一個開源的命令行工具,可以通過它來快速創建 PWA 項目。它提供了多種常用的 APP Shell 給用戶選擇,降低了開發成本,也簡化了工作流程,讓 PWA 項目變得易于管理。
3. 各大站點紛紛實踐,用PWA已成趨勢?
PWA 剛推出時,就獲得了很多大型站點的支持,比如印度最大的電商網站 Flipcart,它是第一個大規模應用 PWA 的站點,也取得了非常好的收益,用戶停留時長增長了 3 倍。除 Flipcart 之外,還有很多不錯的案例。下面我們來看看國內外的兩個站點的實踐案例。
案例1:Twitter Lite PWA
首先,國外的 Twitter 在 2017 年上線了 Twitter Lite PWA, Google 開發者網站上有 Twitter PWA 的案例分析。Twitter Lite PWA 同樣收益驚人:
- 平均用戶停留時長增長 65%
- Web 站點發推的數量增長 75% (Amazing)
- 跳出率降低 20%
Twitter Lite 能取得這樣的成績,歸功于 PWA 的新技術和用戶體驗至上的設計原則:它通過 Service Worker 緩存文件,讓頁面可以離線,同時降低網絡消耗;通過 Web Push 接受服務器推送的消息;采用 App Shell 的設計模型,配合 Service Worker 能讓頁面瞬間展現。
案例2:ele.me PWA
Google 開發者網站上也對 ele.me 的案例進行了 分析。從這個案例分析中,我們可以看到 ele.me PWA 改造的收益如下:
- 預緩存的頁面平均加載時間減少 11.6%
- 所有頁面的平均加載時間減少 6.35%
- 在 3G 網絡并且是第一次加載時,從頁面加載到用戶可操作的時間下降到 4.93s
可見,ele.me 同樣取得了很不錯的收益。不同于 Twitter Lite,ele.me 是 MPA 站點,這會讓站點變的更復雜,并且體驗不如 SPA 那么順暢,但是 ele.me 充分利用了 PWA 的各種新技術和設計模式,將 MPA 的影響降到最小,比如使用了 PRPL 模式,最大程度的降低頁面的首屏時間,還采用了 App Skeleton 的設計方式讓用戶對正在加載的頁面內容有心里預期。
Twitter 和 ele.me 只是 PWA 站點中兩個效果比較顯著的案例,同樣還有很多其他的案例,可以訪問 Google 的案例分析頁面合集:
https://developers.google.cn/web/showcase/
實際收益明顯,再加上 Google 的強力支持,使得 PWA 的增長非常迅速,越來越多的互聯網大站跟進。下面這張圖列出了一些站點,從最開始的 Flipcart,到目前的 Instangram、Uber、Twitter、Starbucks 等,不僅數量在增加,站點等級和質量也在不斷地提升。放眼國內,百度、餓了么、阿里都已經有部分站點支持 PWA 了,滴滴也表示有興趣,可見,PWA 不僅在國外非常受重視,在國內同樣受到各大互聯網企業的重視。
按照當前的發展趨勢,PWA 將會帶來 Web App 的大量需求,新一輪大前端技術洗牌很可能近在眼前了。