從 SPA 到 PWA:Web App的下一站在哪?

從 SPA 到 PWA:Web App的下一站在哪?

作者|楊珺(百度前端資深研發工程師)

從 AJAX(Asynchronous JavaScript + XML,異步 JavaScript 和 XML)開始, 尤其是 AngularJS 推出之後,SPA(Single Page App,單頁應用)已經成為前端 App 的必選方案。

SPA 可以在客戶端提供完整的路由、頁面渲染、甚至一部分數據處理; 這往往需要一個比 jQuery 時代更重的 JavaScript 框架,來實現這些原本發生在後端的邏輯。

多數框架如 React、Vue 還會內置組件化機制來幫助開發者組織代碼, 它們甚至進化到專門負責視圖組件的程度,路由和數據交由各種插件來處理, 比如 vuex、Redux、Vue Router 等等。這些工具已經相當先進和完整,提供了路由方案、服務器端渲染方案、前端狀態管理方案。

但 SPA 的本質還是瀏覽器端 App,底層技術仍然依賴 history API、defineProperty、AJAX。 這些 API 的能力和完備性,決定了 SPA 能達到的用戶體驗和上層架構設計。

也正是這些底層 API 的不足和缺陷使得 SPA 很難企及原始 Web 的架構優勢。 比如在內容可訪問性(Accessibility)、服務的獨立部署和演化(Independent Deployment) 等方面遠不及十年前搭建的同類站點。

同時還在不同程度上破壞了 HTTP、URL、HTML 的語義, 這些缺陷使我們需要花費大量精力去修復日誌統計、性能優化、首屏渲染、靜態分析和測試等環節。而陷阱在於決策使用 SPA 方案時不一定能有足夠的遠見看到這些問題對架構帶來的深遠影響。

與此同時 Web 標準也在持續迭代,諸如 Web Bluetooth、Push API、Web of Things、Service Worker 的標準已經在主流瀏覽器(尤其考慮國內 webkit 內核的普及程度)有不同程度的支持。 尤其是 PWA 概念的提出,給出了一種在不破壞 Web 架構的前提下實現流暢用戶體驗的方式。

本文就 SPA 架構的一些不足展開討論,並探討 PWA 方案(這裡說是方案,其實更是一種技術方向的選擇)的價值和私有平臺的最佳演化方式。

我們想要怎樣的 Web App?

Web 頁面尤其是動態 Web 頁面和 Web App 的區別非常模糊, 但為了更清晰地討論 SPA、PWA 這些技術方案,還是先來定性地分析一下 Web App 背後的產品需求:

  1. 平滑的、不被打斷的交互體驗。如果交互過程中,頁面重新加載而丟失狀態、網絡原因使得頁面無法顯示,這樣用戶體驗就會被打斷,就不夠 App。
  2. 與設備相適應的佈局。例如在移動瀏覽器中展示 PC 頁面的完整佈局,就會使用戶需要縮放和拖動才能查看信息,就不是 App 的體驗。
  3. 快速的呈現和響應。進入每一頁都需要漫長的等待,或者用戶操作後得不到立即反饋,可能是 Web 頁面常見的問題。
  4. 符合移動端的交互習慣。移動端特有的硬件使其 Native API 更加豐富,例如藍牙、二維碼、相機、支付、手勢滑動、手勢縮放、觸感反饋等。

以上是筆者對 Web App 需求的理解(歡迎留下評論),下文基於此展開討論。

Web 架構的優勢

值得思考的是,即使 Web 頁面與我們對移動 App 的需求相差甚遠, Web 技術仍然是當前移動 App 的架構中必備的組成部分。 我們依賴 Web 技術的地方正是 Web 架構的優勢:

  1. 可鏈接。Web 在技術分類上屬於分佈式文檔,這些文檔通過 URL 相互鏈接。無論是單個網站內的不同頁面還是跨網站的頁面之間,都可以直接打開而無需下載安裝。這裡要強調一個隱含的功能:Deep Linking,即從一個 App 跳轉進入另一個 App 內的指定頁面,甚至還可以定位到特定的瀏覽位置。
  2. 可訪問。HTML 是 Web 的基石之一,一方面提供了內容和樣式的分離,使得機器和人都可以閱讀也便於開發更復雜的樣式和交互;另一方面統一的標記語言有更好的可訪問性,這是其他平臺很難建設的,比如可以選擇和複製,盲人可以啟用屏幕閱讀器,甚至可以找命令行中查看一個 Web 頁面。
  3. 零門檻。你不需要任何許可或付費就可以參與開發和提供 Web 服務。這意味著同時存在無數種方式來開發一個網站,在一定程度上促成了 Web 技術的繁榮。
  4. 獨立部署。不同的 Web 服務之間,甚至同一 Web 服務的各部分,都可以獨立地部署和演化。新舊網站可以同時運行在這一平臺上,這一點也是 HTML5 標準的迭代原則。
  5. 健壯性。Web 頁面擁有分佈式系統特有的健壯性。Web 頁面和它所依賴的圖片、視頻、腳本、樣式等資源沒有硬性依賴:一方面部分資源掛掉頁面的其他功能仍然可用;另一方面 Web App 可以一邊下載一邊執行,這是其他平臺很難具有的健壯性。

在 SPA 大行其道之後廣泛討論的兼容性、響應式設計、可訪問性(或稱無障礙)、頁面性能等問題, 本來都是 Web 體系結構的優勢,這是一個略帶調侃的示例頁面:https://motherfuckingwebsite.com

這個只有 81 行的網頁,不僅傳遞了相當多的內容,而且它在兼容性、響應式設計、可訪問性、頁面性能方面都表現優異。

重要的是這個頁面使用的技術都來自 Web 早期,換句話說這些非功能需求正是 Web 與生俱來的優勢。既然我們正在費力解決的這些問題不來自於 Web 本身,那麼這些問題到底來自哪裡? 是重 JavaScript 框架的問題,還是組件化方案的問題,還是掉進開發者體驗陷阱?

SPA 方案的困難

本文不去討論某個具體的 SPA 框架的成敗或優缺點,只討論採用 SPA 方案來實現我們想要的 Web App 存在哪些困難,以及 SPA 方案對既有 Web 頁面的影響。 下面列舉 SPA 方案對架構產生的一些比較重要的影響,從可鏈接性(URL)、可訪問性,服務的獨立性等方面具體分析。

SPA 是一組高度耦合的頁面(頁面耦合)

SPA 方案要求 App 內所有頁面位於同一服務實例上, 也就是說處理 SPA 頁面請求的每個實例都必須擁有 App 內所有頁面的信息, 這一信息通常是頁面組件的聲明。

這是因為 SPA 要求頁面切換不發生瀏覽器跳轉。設想操作流程『打開頁面 A -> pushState 到頁面 B -> 刷新 -> 返回』,這時瀏覽器不會重新加載 A,而只是觸發 popstate 事件給 B。 因此對於任意頁面 A,點出到的任意頁面 B,B 頁面反過來都需要知道頁面 A 的信息,當然頁面 A 也知道頁面 B 的信息,因此任意兩個有跳轉關係的頁面,都需要相互瞭解對方的信息,或引用對方組件。

這樣相互耦合的一組頁面,就構成了一個 SPA 方案的 Web App。 這樣的 App 內所有頁面都不再能夠『獨立部署』,因此也不能獨立迭代演化。

這往往意味著它們的開發調試、前端編譯、部署過程都是耦合在一起的, 這些都是 SPA 方案帶來的成本:

  • 開發依賴:因為要能夠打開一個頁面必須引用對應的組件,這些組件在開發和調試階段一定需要綁在一起。如果兩個頁面涉及到業務會跨團隊,無疑會增加很多成本。
  • 編譯依賴:考慮使用 MD5 戳的編譯方法,相互引用的一組文件必須一起編譯上線,這會降低協作效率因為它們本屬於不同的業務或團隊。當然也可以不使用 MD5 戳並分別上線,動態調整引用關係,這樣的問題在於無法平衡 HTTP 緩存和快速生效的矛盾。

此外,由於瀏覽器的同源策略,一個 Web App 被限制共享一個域名。 否則在富交互的場景下跨域將會是一個非常複雜的問題, 當然如果你願意使用 JSONP 這麼不安全的接口另當別論。

強組件化容易陷入技術豎井(技術封閉)

SPA 方案伴隨著強組件化方案,容易陷入封閉的技術豎井。 換句話說就是容易一條路走到黑,失去 Web 應有的架構優勢。 這是因為異步頁面擁有異步的天性。 瀏覽器重新渲染一個頁面時, 全局變量、定時器、事件監聽器都會初始化為全新的,這是『刷新』的含義。 而異步頁面卻不然:

  • 異步頁面間,全局變量、定時器是共享的,沒有託管很容易亂掉。
  • 異步頁面的


分享到:


相關文章: