PWA 的探索與最佳實踐

4月20-22日 QCon 全球軟件開發大會在北京召開,做爲 InfoQ 舉辦的全球頂級技術盛會,總共彙集了 2500 名資深開發者參會,百度資深前端工程師彭星受邀參加大會,並在「前端實踐思考和探索「專場分享了關於百度在 PWA 方面的探索與最佳實踐。本文根據彭星的演講整理而成。

PWA 是在 Web 端具備顛覆性的一個概念,在國外已經被廣泛接受,不少站點已經改形成 PWA,而且取得了很是好的成績。例如 twitter 改造 PWA 完成後,twitter lite 平均用戶停留時長增加了65%。在國內,PWA 的概念愈來愈被普遍接受,微博、餓了麼等不少大型的站點都已經改形成 PWA,而且還有更多的站點正在進行改造。css

PWA 是什麼前端

對於 PWA 來講,用戶體驗纔是核心。PWA 不是一項具體的技術,他是應用了一系列技術進行使用體驗優化後的Web APP,具備與Native App 一致的用戶體驗,可以添加主屏圖標、離線可用、接收離線通知等。具體詳情查看 Demo 演示。vue

PWA 具備三個主要的特性 git

  • 可靠  一方面是指 PWA 的安全性,PWA 只能運行在 HTTPS 上;另外一方面是指在網絡不穩定或者沒網狀況下,PWA 依然能夠訪問。 github

  • 快速  快速響應用戶的交互行爲,而且具備平滑流暢的動畫、加載速度、渲染速度和渲染性能等。 shell

  • 用戶粘性  經過添加到桌面以及離線消息推送,能帶來用戶的第二次訪問,而且依靠良好的用戶體驗吸引用戶再次訪問。 json

PWA 的核心技術瀏覽器

PWA 不是一項單獨的技術,技術包括 Web App Manifest、Service Worker、Push API & Notification API 、App Shell & App Skeleton 等等技術,接下來咱們重點介紹幾項技術以及相關問題的解決方法。緩存

Web App Manifest安全

Web App Manifest 是支持站點在主屏上建立圖標的技術方案,而且定製 PWA 的啓動畫面的圖標和顏色等,以下圖:

Web App Manifest 功能雖然強大,可是技術上並不難,就是一個外鏈的 json 文件,經過 link 來引入:<link rel="manifest" href=「/assets/manifest.json」>,文件的具體內容以下:

Web App Manifest 的標準裏還有不少其餘的字段,能夠去 W3C 的標準裏查找

https://w3c.github.io/manifest

Service Worker

Service Worker 是 PWA 中最重要的概念之一,它是一個特殊的 Web Worker,獨立於瀏覽器的主線程運行,特殊在它能夠攔截用戶的網絡請求,而且操做緩存,還支持 Push 和後臺同步等功能。

Service Worker 經過 Cache Storage 、Cache API 操做本地緩存,以及經過 fetch API 請求服務器端數據,不論是否有網絡鏈接,或者站點發生了 404 、500,均可以讓用戶看到特殊定製的錯誤頁面,而不是瀏覽器的默認 404 頁面。

App Shell 和 App Skeleton

PWA 一般是 SPA 且一般採用 App Shell 設計模型。App Shell 在 PWA 裏是很是重要的一個概念,那麼 App Shell 是什麼呢?

App Shell 是指支持頁面所需的最小的 HTML、CSS 和 JavaScript 的資源集合。一旦離線,能夠確保在用戶重複訪問時提供即時、可靠的良好性能,下面的截圖是 App Shell 展示給用戶的部分

以 Vue 的項目舉例,AppShell 包含:

  1. 入口 HTML 文件

  2. 打包好的 Vendor JS 文件

  3. 導出的 CSS 文件

如上圖所示,App Shell 渲染出了 header 部分,那麼正文部分在加載數據以前,都是白屏,這對於用戶來講體驗很是很差,有一個名詞叫骨架屏(App Skeleton),在渲染出數據以前,在白屏位置佔位,儘可能不出現長時間的白屏。

App Skeleton 須要在最短的時間內渲染給用戶,因此,通常狀況下,會將 App Skeleton 編譯到 HTML 裏,就像下面的代碼,指望瀏覽器在加載完 HTML 以後就能先顯示骨架屏。

可是<link rel=「stylesheet」 href=「/static/index.css」> 會阻塞骨架屏的渲染,直到 CSS 文件加載完成以後,瀏覽器纔會渲染出骨架屏,這樣用戶看到的白屏時間會比預想中的長。這個問題不多有站點會注意到,即便作了骨架屏,也不必定會解決 CSS 加載阻止骨架屏渲染的問題,好比餓了麼的 PWA 首頁就沒解決。

那麼,咱們怎麼解決這個問題呢,能夠經過 link 的 preload 解決,preload 不會阻止 HTML 渲染,在 preload 的資源加載完成以後,改回 stylesheet,調用 mount 來展示 JS 的渲染結果。以下面的代碼所示(下面的代碼並不能直接運行,只用來代表思路)

除了經過 preload 的這種方式解決以外,還能夠將 link 裏的 CSS 內聯到 JS 裏面,Vue 的項目默認就是 CSS In JS 的。

PWA 全稱是 Progressive Web Apps,意味着是漸進式的,也就是在現有的基礎上進行逐漸添加,從而改善用戶體驗,並不須要推倒重來,對整個站點進行改造。

PWA SEO 問題解決方案

SEO 是每一個站點都很關心的問題,PWA 一般是 SPA,衆所周知,傳統的搜索引擎是沒法索引經過 JS 來渲染的頁面的,那麼,咱們須要怎麼解決這個問題?

首先須要說明的是百度不是那個傳統的搜索引擎,百度、Google 都是可以索引移動端的 SPA 頁面的。那麼對於其餘搜索引擎,解決 PWA SEO 的問題惟一方法就是服務器端渲染(SSR),如今市面上主流的 MVVM 框架都有提供 SSR 的解決方案,好比 React、Vue、San 等。

SSR 的頁面是服務器直出的,內容頁是同時出來的,那麼這種方式如何結合 Service Worker 來離線呢?如何作到 AppShell 的啓動效果呢?咱們採用 Service Worker + App Shell + SSR + (Vue/React/San) 的方案來很是完美的解決這個問題。

第一次請求,服務器直接輸出 SSR 以後的內容,頁面加載完成以後註冊 Service Worker,Service Worker 在 install 階段預緩存一些靜態文件或者其餘資源,在這裏咱們新增一個請求,地址是 /appshell,這個 /appshell 的請求返回的內容是 App Shell 的 HTML,這個 HTML 有引用 JS 和 CSS 的代碼,能夠舉一個 Vue 的例子:

https://github.com/lavas-project/lavas-template-vue/blob/release-basic/pages/Appshell.vue

在第二次請求的時候,Service Worker 經過request.mode === ‘navigate’ 來判斷當前這個請求是不是頁面請求,若是是,將事先緩存好的 /appshell HTML 結構返回給頁面,渲染以後,App Shell 經過當前 URL 去請求對應的 JS 和數據來渲染頁面的正文內容。

經過這種方式,不只可以解決 SEO 的問題,站點能徹底離線,還能縮短白屏時間,更重要的一點是它還能大大下降服務器 SSR 帶來的壓力。由於用戶只有第一次渲染才須要服務器運行 SSR 的邏輯,以後的請求都是走的前端渲染。

PWA 的兼容性

PWA 在 2017 年初,僅僅 Chrome 和 Firefox 支持 PWA,通過一年的發展,國內主流瀏覽器都已經支持 PWA,iOS 在 新發布的11.3 版本中也支持了 PWA。

推薦

更多 PWA 教程、文檔、Lavas 官網、Codelab、PWA 效果示例、兼容性請訪問 Lavas 官網,點擊左下角「閱讀原文」便可進入官網。

Brilliant Open Web 

BOW(Brilliant Open Web)團隊,是一個專門的 Web 技術建設小組,致力於推進 Open Web 技術的發展,讓 Web 從新成爲開發者的首選。

BOW 關注前端,關注 Web;剖析技術、分享實踐;談談學習,也聊聊管理。

關注 Open Web 開發者,回覆「加羣」,讓咱們一塊兒推進 Open Web 技術的發展!

相關文章
相關標籤/搜索