多來源網站的漸進式網頁應用程式

在多原點網站中建構漸進式網頁應用程式的挑戰和因應方法。

Demián Renzulli
Demián Renzulli

背景

過去,使用多原點架構有一些優點,但對於漸進式網頁應用程式來說,這種做法會帶來許多挑戰。具體來說,同源政策會針對共用服務工作者和快取、權限,以及在多個來源中提供獨立體驗等事項,設下限制。本文將說明多個來源的優缺點,並說明在多個來源網站中建構漸進式網頁應用程式的挑戰和解決方法。

多個來源的正確和不當用法

網站採用多原點架構有幾個正當理由,大多與提供獨立的網頁應用程式集合,或建立彼此完全隔離的體驗有關。也有一些用途應避免使用。

優良範例

首先,我們來看看實用的原因:

  • 本地化/語言:使用國家/地區代碼頂層網域,將要提供給不同國家/地區的網站區隔開來 (例如 https://www.google.com.ar),或是使用子網域將指定不同地點的網站區隔開來 (例如https://newyork.craigslist.org),或是提供特定語言的內容 (例如 https://en.wikipedia.org)。

  • 獨立的 webapps:使用不同的子網域,提供與主要來源網站目的大不相同的體驗。舉例來說,在新聞網站中,您可以刻意從 https://crosswords.example.com 提供填字遊戲網頁應用程式,並將其安裝及使用為獨立 PWA,不必與主要網站共用任何資源或功能。

缺點

如果您沒有執行上述任何操作,在建構漸進式網頁應用程式時,使用多原點架構可能會帶來不利影響。

儘管如此,許多網站仍會無緣無故或基於「舊版」原因,繼續採用這種結構。舉例來說,使用子網域將網站的部分內容隨意分開,而這些內容應屬於統一體驗的一部分。

舉例來說,我們強烈建議您避免採用下列模式:

  • 網站專區:在子網域中分隔網站的不同專區。在新聞網站中,首頁通常會位於 https://www.example.com,體育版位於 https://sports.example.com,政治版位於 https://politics.example.com 等等。以電子商務網站為例,可以使用 https://category.example.com 標示產品類別,https://product.example.com 標示產品頁面等。

  • 使用者流程:我們不建議將網站的不同小部分分開,例如子網域中的登入或購物流程頁面。例如使用 https://login.example.comhttps://checkout.example.com

如果無法遷移至單一來源,請參閱以下清單,瞭解相關挑戰,並在建構漸進式網頁應用程式時,考慮可能的解決方法。

跨不同來源的 PWA 相關問題與解決方法

在多個來源上建構網站時,要提供統一的 PWA 體驗相當困難,主要是因為同源政策會設下許多限制。讓我們逐一檢查。

Service Worker

服務工作者指令碼網址的來源必須與呼叫 register() 的網頁來源相同。舉例來說,https://www.example.com 中的網頁無法使用 https://section.example.com 中的服務工作者網址呼叫 register()

另一個考量因素是,Service Worker 只能控管在其所屬來源和路徑下代管的網頁。也就是說,如果 Service Worker 託管在 https://www.example.com,則只能控制該來源的網址 (依據 scope 參數中定義的路徑),但無法控制其他子網域中的任何網頁,例如 https://section.example.com 中的網頁。

在這種情況下,唯一的解決方法就是使用多個服務工作站 (每個來源一個)。

快取

Cache 物件、indexedDB 和 localStorage 也受到單一來源限制。這表示無法從 https://www.section.example.com 存取屬於 https://www.example.com 的快取,例如:https://www.section.example.com

在這種情況下,您可以採取下列做法來妥善管理快取:

  • 善用瀏覽器快取:建議您一律採用傳統瀏覽器快取最佳做法。這項技術提供額外的好處,可在不同來源之間重複使用快取資源,而這項功能無法透過服務工作者的快取功能實現。如要瞭解如何搭配服務工作者使用 HTTP 快取的最佳做法,請參閱這篇文章

  • 保持服務工作者安裝程序輕量化:如果您維護多個服務工作者,請避免讓使用者每次前往新來源時,都必須支付高額安裝費用。換句話說,請只預先快取絕對必要的資源。

權限

權限的範圍也包含來源。這表示如果使用者將特定權限授予來源 https://section.example.com,該權限就不會套用至其他來源,例如 https://www.example.com

由於無法跨來源共用權限,因此唯一的解決方案是在需要特定功能 (例如位置) 的每個子網域上要求權限。針對網路推播等功能,您可以保留 Cookie,以便追蹤使用者是否已在其他子網域中接受權限,避免再次要求權限。

安裝

如要安裝 PWA,每個來源都必須有自己的資訊清單,且 start_url 相對於自身。也就是說,如果使用者在特定來源 (例如 https://section.example.com) 中收到安裝提示,就無法在其他來源 (例如 https://www.example.com) 中安裝 start_url PWA。換句話說,如果使用者在子網域中收到安裝提示,就只能安裝子頁面的 PWA,而無法安裝應用程式的主網址。

此外,如果每個子網域都符合安裝條件,使用者在瀏覽網站時可能會收到多次安裝提示,並收到安裝 PWA 的提示。

如要緩解這個問題,請確保提示只會顯示在主要來源上。當使用者造訪通過安裝條件的子網域時:

  1. 接聽 beforeinstallprompt 事件
  2. 避免提示顯示,請呼叫 event.preventDefault()

這樣一來,您就能確保提示不會顯示在網站的非預期位置,同時仍可繼續顯示在主要來源 (例如首頁) 中。

獨立模式

在獨立視窗中瀏覽時,如果使用者移動到 PWA 資訊清單所設範圍之外,瀏覽器的行為就會有所不同。實際情況取決於各個瀏覽器版本和供應商。舉例來說,當使用者在獨立模式下離開範圍,最新版 Chrome 會開啟 Chrome 自訂分頁

在大多數情況下,這並沒有解決方案,但您可以針對代管在子網域中的體驗 (例如登入工作流程) 的小部分,採用替代做法:

  1. 新的網址 https://login.example.com 可在全螢幕 iframe 中開啟。
  2. 在 iframe 中完成工作 (例如登入程序) 後,您可以使用 postMessage(),將 iframe 中的所有結果資訊傳回至父頁面。
  3. 最後,主頁面收到訊息後,您可以取消註冊事件監聽器,並從 DOM 移除 iframe。

結論

同源政策會對多個來源建立的網站施加許多限制,這些網站希望能提供一致的 PWA 體驗。因此,為了為使用者提供最佳體驗,我們強烈建議您不要將網站劃分為不同的原始來源。

對於以這種方式建構的現有網站,要讓多原點 PWA 正常運作可能會很困難,但我們已探索一些潛在的解決方法。每種方法各有優缺,因此請根據您的判斷,決定在網站上採用哪種方法。

評估長期策略或網站重新設計時,請考慮遷移至單一來源,除非有重要原因需要保留多來源架構。

感謝 Penny Mclachlan、Paul Covell、Dominick Ng、Alberto Medina、Pete LePage、Joe Medley、Cheney Tsai、Martin Schierle 和 Andre Bandarra 提供技術審查和建議。