重點摘要:Extensions API 已更新,以便支援往返快取,預先載入導覽。詳情如下。
Chrome 一直致力於提升瀏覽速度。即時導覽技術 (例如 往返快取,已在 Chrome 96 的電腦上推出) 和推測規則 (已在 Chrome 103 中推出) 可改善前往和返回的體驗。本文將探討我們為因應這些新工作流程而對瀏覽器擴充功能 API 所做的更新。
瞭解頁面類型
在推出往返快取和預先算繪功能之前,每個分頁只有一個有效網頁。這一直是顯示的內容。如果使用者返回上一頁,系統會刪除目前的網頁 (網頁 B),並完全重建歷史記錄中的上一頁 (網頁 A)。擴充功能不需要擔心網頁處於生命週期中的哪個階段,因為分頁只有一個狀態 (啟用/顯示)。
有了往返快取和預先顯示功能,分頁和網頁之間就不再是一對一關係。如今,每個分頁實際上都會儲存多個頁面,並在狀態之間進行頁面轉換,而非遭到銷毀和重建。
舉例來說,網頁一開始可能會以預先算繪 (不可見) 的形式存在,在使用者點選連結時轉換為有效 (可見) 網頁,然後在使用者瀏覽其他網頁時儲存在返回/前進快取 (不可見) 中,而不會遭到刪除。在本文稍後的部分,我們將探討公開的新屬性,協助擴充功能瞭解網頁的狀態。
請注意,分頁可以有一系列預先算繪的網頁 (不只一個)、單一有效 (可見) 網頁,以及一系列快取的「返回」/「前進」網頁。
這對擴充功能開發人員有何影響?
FrameId == 0
在 Chromium 中,我們將最上層/主頁框稱為最外層頁框。
假設最外層框架的 frameId 為 0 (先前的最佳做法) 的擴充功能作者,可能會發生問題。由於分頁現在可以有多個最外層框架 (預先算繪和快取的網頁),因此假設分頁只有一個最外層框架的假設是不正確的。frameId == 0
仍會繼續代表有效頁面的最外層框架,但同一個分頁中其他頁面的最外層框架會設為非零值。我們已新增「frameType」frameType欄位來修正這個問題。請參閱本篇文章的「如何判斷某個影格是否為最外層影格?」一節。
影格和文件的生命週期
另一個與擴充功能相關的問題是影格生命週期。框架會代管文件 (與已提交的網址相關聯)。文件可能會變更 (例如透過導覽),但 frameId 不會變更,因此很難只透過 frameId 連結特定文件中的事件。我們正在推出 documentId 概念,這是每份文件的專屬 ID。如果導覽框架並開啟新文件,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。
我們可以將 DocumentLifecycle
與 FrameType
合併,並判斷影格是否為有效的外層影格。例如:tab.documentLifecycle === “active” && frameType === “outermost_frame”
如何解決使用時間與影格相關的問題?
如上所述,框架會代管文件,且框架可能會導向新文件,但 frameId
不會變更。當您收到只包含 frameId
的事件時,就會發生問題。如果您查詢框架的網址,可能會發現該網址與事件發生時的網址不同,這稱為使用時間問題。
為解決這個問題,我們引入了 documentId
(以及 parentDocumentId
)。如果提供 documentId
,webNavigation.getFrame() 方法現在會讓 frameId
成為選用項目。每當導覽畫格時,documentId
就會變更。
如何判斷頁面轉換的時間?
系統會透過明確的信號,判斷網頁在不同狀態之間的轉換時間。
我們來看看 WebNavigation
事件。
首次瀏覽任何網頁時,您會看到以下順序的四個事件。請注意,當 DocumentLifecycle
狀態為 "prerender"
或 "active"
時,可能會發生這四個事件。
onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted
下圖說明瞭這項情況,顯示預先轉譯的網頁成為有效網頁時,documentId
會變更為 "xyz"
。
當網頁從「往返快取」或「預先算繪」轉換為「有效」狀態時,系統會產生另外三個事件 (但 DocumentLifecyle
為 "active"
)。
onBeforeNavigate
onCommitted
onCompleted
documentId
會與原始事件相同。如上所述,當 documentId
== xyz 啟用時,就會發生這種情況。請注意,由於網頁已載入,因此除了 onDOMContentLoaded
事件外,其他相同的導覽事件都會觸發。
如有任何意見或問題,歡迎在 chromium-extensions 群組中提出。