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

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

Demián Renzulli
Demián Renzulli

背景

過去,採用多來源架構有一些好處,但對於漸進式網頁應用程式而言,這種做法會帶來許多挑戰。尤其是同源政策,對於共用 Service Worker、快取和權限等項目設有限制,以及在多個來源之間提供獨立體驗。本文將介紹多個來源的良好與不當使用行為,並說明在多來源網站上建構漸進式網頁應用程式時會遇到的挑戰和解決方法。

使用多個來源的良好和不當使用方法

網站採用多來源架構的正當原因有很多,其中多數原因在於提供一組獨立的網頁應用程式,或是打造完全獨立的體驗。除此之外,也應該避免使用。

優良範例

讓我們先來看看這些實用原因:

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

  • 獨立網頁應用程式:使用不同子網域來提供用途與主要來源網站差異很大的體驗。例如,在新聞網站上,填字應用程式可能是由 https://crosswords.example.com 刻意提供,然後是安裝和做為獨立 PWA 使用,無須與主網站分享任何資源或功能。

不佳

如果您沒有執行上述任何操作,那麼在建立 Progressive Web Apps 時,使用多來源架構可能會是一大缺點。

儘管如此,許多網站仍因沒有特定原因而持續採用這種方式結構,或是因為「舊版」的原因。例如,使用子網域任意分隔網站中應屬於統合體驗的部分。

我們強烈建議使用以下模式:

  • 網站區塊:用來區分網站上不同的子網域。在新聞網站上,瀏覽首頁通常位於 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

Service Worker 指令碼網址的來源必須與呼叫 register() 的網頁來源相同。也就是說,https://www.example.com 的網頁無法透過 https://section.example.com 使用 Service Worker 網址呼叫 register()

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

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

快取

Cache 物件、已建立索引的資料庫和 localStorage 也受限於單一來源。這表示無法存取屬於 https://www.example.com 的快取,例如:https://www.section.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. 最後,在主頁面收到訊息後,您可以取消註冊監聽器,並將 iframe 最終從 DOM 中移除。

結論

如果網站是以多個來源為基礎建構而成,且想要提供一致的 PWA 體驗,同來源政策會施加許多限制。因此,為了提供最佳的使用體驗,我們強烈建議不要將網站分割成不同的來源。

對於以這種方式建構的現有網站,要讓多來源 PWA 正確運作並不容易,但我們已探索了一些可行的解決方法。各類型可能各有優缺點,因此請謹慎評估網站採取的策略。

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

感謝許多創作者提供的技術審查和建議:Penny Mclachlan、Paul Covell、Dominick Ng、Alberto Medina、Pete LePage、Joe Medley、Chney Tsai、Martin Schierle 和 Andre Bandarra。