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

Dave Tapuska
Dave Tapuska

重點摘要:Extension API 經過更新,可支援往返快取和預先載入瀏覽功能。詳情如下。

Chrome 不斷在加快瀏覽速度。使用即時導覽技術,例如返回/轉送快取 (適用於 Chrome 96 的電腦版推送) 和推測規則 (在 Chrome 103 版中推出) 可改善往返體驗。在本文中,我們將探索我們對瀏覽器擴充功能 API 所做的更新,以因應這些新的工作流程。

瞭解網頁類型

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

移除使用中的網頁
移除使用中的網頁。

透過往返快取和預先算繪,分頁和頁面之間不再是單一關係。現在,每個分頁會實際儲存多個狀態在狀態之間轉換的多個頁面和頁面,而不會被刪除並重建。

舉例來說,頁面可能會以預先算繪 (未顯示) 的頁面開頭,在使用者點選連結時轉換為有效 (可見) 頁面,然後在使用者前往其他頁面時,儲存在往返快取 (不會顯示) 中,整個頁面也不會遭到刪除。本文稍後將介紹公開的新屬性,協助擴充功能瞭解頁面的狀態。

網頁類型
網頁類型。

請注意,分頁標籤可以包含一系列預先轉譯頁面 (而不只是一個頁面)、單一「有效」 (可見) 頁面,以及一系列往返快取頁面。

本次異動對擴充功能開發人員有何影響?

FrameId == 0

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

假設最外框架的 frameId 為 0 (先前的最佳做法) 的擴充功能作者可能會發生問題。由於一個分頁現在可以有多個外部頁框 (預先轉譯和快取的頁面),因此系統會假設分頁有一個最外層的影格不正確。frameId == 0 會繼續呈現「使用中」頁面的最外影格,但同一個分頁中「其他」頁面最外層的影格數不會是零。為修正這個問題,我們已新增 frameType 欄位。請參閱本文的「如何判斷影格是否為最外層?」一節。

影格與文件的生命週期

擴充功能的另一個問題是影格的生命週期。頁框可代管文件 (與已修訂網址相關聯)。文件可以變更 (例如瀏覽),但 frameId 不會,因此很難將特定文件中發生的內容和只與 frameId 建立關聯。我們將推出 documentId 的概念,這是每份文件的唯一識別碼。如果使用者瀏覽頁框並開啟新文件,ID 就會變更。這個欄位可用來判斷頁面變更生命週期狀態 (在預先算繪/主動/快取之間) 的時間是否相同,因為這個欄位會保持不變。

網站導覽事件

視所屬生命週期而定,chrome.webNavigation 命名空間中的事件可能會在同一個頁面上多次觸發。請參閱「如何判斷網頁所屬的生命週期?」和「如何判斷網頁轉換的時機?」兩節。

如何判斷網頁所屬的生命週期?

針對先前可使用 frameId 的許多擴充功能 API,系統已新增 DocumentLifecycle 類型。如果事件有 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,並判斷影格是否為使用中的最外層影格。例如:js 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 群組提問。