Chrome 擴充功能:擴充 API 以支援即時導覽功能

Dave Tapuska
Dave Tapuska

重點摘要:Extensions API 已更新,可支援往返快取,預先載入導覽。詳情如下。

Chrome 不斷在加快瀏覽速度。即時導覽技術 (例如往返快取 (在 Chrome 96 的電腦上已推出) 和推測規則 (在 Chrome 103 中已推出) 等) 可改善前往和返回的體驗。本文將探討我們為因應這些新工作流程而對瀏覽器擴充功能 API 所做的更新。

瞭解頁面類型

在引入往返快取和預先算繪之前,個別分頁只會有一個有效頁面。這一直是顯示的內容。如果使用者返回上一頁,系統會刪除目前的網頁 (網頁 B),並完全重建歷史記錄中的上一頁 (網頁 A)。因此擴充功能不必擔心生命週期頁面位於哪個部分,因為分頁只有一個 (啟用/可見狀態)。

淘汰目前的頁面
將有效頁面逐出。

透過往返快取和預先算繪,分頁和頁面之間不再是單一關係。如今,每個分頁實際上都會儲存多個頁面,並在狀態之間進行頁面轉換,而非遭到銷毀和重建。

舉例來說,網頁一開始可能會以預先算繪 (不可見) 的形式存在,然後在使用者點選連結時轉換為有效 (可見) 的網頁,再在使用者瀏覽其他網頁時儲存在返回/前進快取 (不可見) 中,而這一切都不會導致網頁遭到刪除。在本文稍後的部分,我們將探討公開的新屬性,協助擴充功能瞭解網頁的狀態。

頁面類型
網頁類型。

請注意,分頁可以有一系列預先算繪的網頁 (不只一個)、單一有效 (可見) 網頁,以及一系列快取的「返回」/「前進」網頁。

這對擴充功能開發人員有何影響?

FrameId == 0

在 Chromium 中,最上層/主要頁框稱為最外層。

假設最外層框架的 frameId 為 0 (先前的最佳做法) 的擴充功能作者,可能會發生問題。由於分頁現在可以有多個最外層框架 (預先算繪和快取的網頁),因此假設分頁只有一個最外層框架的假設是不正確的。frameId == 0 仍會繼續代表有效頁面的最外層框架,但同一個分頁中其他頁面的最外層框架會設為非零值。我們已新增「frameType」欄位來修正這個問題。請參閱本篇文章的「如何判斷某個影格是否為最外層影格?」一節。

影格和文件的生命週期

另一個與擴充功能相關的問題是影格生命週期。框架會代管文件 (與已提交的網址相關聯)。文件可能會變更 (例如透過導覽),但 frameId 不會變更,因此很難只透過 frameId 連結特定文件中的事件。我們將推出 documentId 的概念,這是每份文件的唯一識別碼。如果導覽框架並開啟新文件,ID 就會變更。這個欄位可用於判斷網頁何時變更生命週期狀態 (在預先算繪/有效/快取之間),因為它會保持不變。

網頁導覽事件

根據生命週期,chrome.webNavigation 命名空間中的事件可以在同一個網頁上觸發多次。請參閱「如何判斷網頁處於哪個生命週期?」和「如何判斷網頁轉換的時間?」兩節。

如何判斷網頁處於哪個生命週期?

DocumentLifecycle 類型已新增至先前提供 frameId 的多個擴充功能 API。如果事件中包含 DocumentLifecycle 類型 (例如 onCommitted),其值就是事件產生的狀態。您隨時可以透過 WebNavigation getFrame()getAllFrames() 方法查詢資訊,但建議您一律使用事件中的值。如果您使用這兩種方法,請注意,在事件產生和兩種方法傳回的承諾解決之間,影格狀態可能會有所變更。

DocumentLifecycle 的值如下:

  • "prerender":目前未向使用者顯示,但可能會向使用者顯示。
  • "active":目前向使用者顯示。
  • "cached":儲存在往返快取中。
  • "pending_deletion":文件正在遭到刪除。

如何判斷某個影格是否為最外層影格?

先前的擴充功能可能會檢查 frameId == 0,以判斷事件是否發生在最外層框架。由於分頁中含有多個網頁,因此我們現在有多個最外層框架,因此 frameId 的定義有問題。您永遠不會收到與往返快取影格相關的事件。不過,對於預先算繪的框架,frameId 會為最外層框架的非零值。因此,使用 frameId == 0 做為判斷最外層的影格是否有誤。

為協助您完成這項操作,我們推出了名為 FrameType 的新類型,讓您輕鬆判斷框架是否確實為最外層的框架。FrameType 具有下列值:

  • "outermost_frame":通常稱為最上層影格。請注意,這些項目有重複的部分。舉例來說,如果您有預先算繪及快取的網頁,每個網頁都有一個最外層的框架,可稱為最頂層的框架。
  • "fenced_frame":保留供日後使用。
  • "sub_frame":通常為 iframe。

我們可以結合 DocumentLifecycleFrameType,並判斷影格是否為使用中的最外層影格。例如:tab.documentLifecycle === “active” && frameType === “outermost_frame”

如何解決使用時間與影格相關的問題?

如前文所述,頁框代管文件,頁框可能會前往新文件,但 frameId 不會改變。如果收到只有 frameId 的事件,這會造成問題。如果您查詢框架的網址,可能會發現該網址與事件發生時的網址不同,這稱為使用時間問題。

為解決這個問題,我們推出了 documentId (和 parentDocumentId)。如果提供 documentIdwebNavigation.getFrame() 方法現在會將 frameId 變為選用。每次瀏覽影格時,documentId 都會變更。

如何判斷頁面轉換的時間?

我們會使用明確的信號,判斷網頁在狀態之間轉換的時間。

我們來看看 WebNavigation 事件

首次瀏覽任何網頁時,您會看到以下順序的四個事件。請注意,當 DocumentLifecycle 狀態為 "prerender""active" 時,可能會發生這四個事件。

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

如下圖所示,當預先算繪頁面變為使用中頁面時,documentId 會變更為 "xyz"

當預先算繪的網頁成為有效網頁時,documentId 會變更
當預先算繪頁面成為有效頁面時,documentId 會變更。

當網頁從「往返快取」或「預先算繪」轉換為「有效」狀態時,系統會產生另外三個事件 (但 DocumentLifecyle"active")。

onBeforeNavigate
onCommitted
onCompleted

documentId 會與原始事件相同。如上所示,當 documentId == xyz 啟用時,就會發生這種情況。請注意,除了 onDOMContentLoaded 事件外,系統會觸發相同的導覽事件,因為頁面已載入。

如有任何意見或問題,歡迎在 chromium-extensions 群組中提出。