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

在多來源網站中建構漸進式網頁應用程式時遇到的挑戰和解決方法。

Demián Renzulli
Demián Renzulli

發布日期:2019 年 8 月 19 日

過去使用多來源架構有一些優點。 對於漸進式網頁應用程式而言,這種做法會帶來許多挑戰。特別是同源政策,會限制服務工作站和快取、權限等項目的共用,以及在多個來源中實現獨立體驗。

瞭解多個來源的優缺點,並說明在多來源網站中建構漸進式網頁應用程式時遇到的挑戰和解決方法。

多個來源的良好和不良用途

網站採用多來源架構有幾個正當理由,主要是為了提供獨立的網頁應用程式集,或是建立完全隔離的體驗。此外,也應避免使用。

優良範例

請先查看實用原因:

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

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

壞處

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

儘管如此,許多網站仍繼續以這種方式建構,沒有特別的原因,或是因為「舊版」原因。舉例來說,如果網站的某些部分應提供統一體驗,卻使用子網域任意分隔,就是不當做法。

舉例來說,我們極不建議使用下列模式:

  • 網站區段:在子網域上分隔網站的不同區段。在新聞網站中,常見的首頁網址為 https://www.example.com,而體育、政治等專區的網址則分別為 https://sports.example.comhttps://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 的網頁無法呼叫 register(),且服務工作人員網址位於 https://section.example.com

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

在這種情況下,唯一的解決方法是使用多個 Service Worker (每個來源一個)。

快取

Cache 物件、indexedDB 和 localStorage 也僅限於單一來源。也就是說,您無法從 https://www.section.example.com 等位置存取 https://www.example.com 所屬的快取。

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

  • 善用瀏覽器快取:建議一律採用傳統瀏覽器快取最佳做法。這項技術還有一項額外優點,就是能跨來源重複使用快取資源,這是 Service Worker 快取無法做到的。如要瞭解如何搭配服務工作人員使用 HTTP 快取,請參閱這篇文章

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

權限

權限也僅限於來源。也就是說,如果使用者將特定權限授予來源 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 提供技術審查和建議。