Google Chrome-Erweiterungen: Erweiterung der API zur Unterstützung der sofortigen Navigation

Dave Tapuska
Dave Tapuska

Zusammenfassung: Die Extensions API wurde aktualisiert, um den Back-Forward-Cache zu unterstützen und Navigationen vorab zu laden. Weitere Informationen dazu findest du unten.

Chrome hat hart daran gearbeitet, die Navigation schneller zu machen. Technologien für die Schnellnavigation wie der Back-Forward-Cache (in Chrome 96 auf dem Computer versendet) und die Spekulationsregeln (in Chrome 103 ausgeliefert) verbessern sowohl das Zurückgehen als auch die Zukunft. In diesem Beitrag stellen wir die Änderungen an den APIs für Browsererweiterungen vor, die diesen neuen Workflows entsprechen.

Die verschiedenen Seitentypen

Vor der Einführung des Back-Forward-Cache und des Pre-Renderings hatte ein einzelner Tab nur eine aktive Seite. Dieser war immer sichtbar. Wenn ein Nutzer zur vorherigen Seite zurückkehrt, wird die aktive Seite gelöscht (Seite B) und die vorherige Seite im Verlauf vollständig rekonstruiert (Seite A). Für Erweiterungen war es nicht erforderlich, in welchem Teil der Lebenszyklusseiten sich die Seiten befanden, da es für einen Tab nur einen aktiven/sichtbaren Status gab.

Aktive Seite entfernen
Entfernung der aktiven Seite.

Mit dem Back-Forward-Cache und dem Pre-Rendering gibt es keine 1:1-Beziehung zwischen Tabs und Seiten mehr. Auf jedem Tab werden jetzt mehrere Seiten und Seitenübergänge zwischen den Zuständen gespeichert, anstatt gelöscht und rekonstruiert zu werden.

Eine Seite kann beispielsweise als vorab gerenderte (nicht sichtbare) Seite beginnen, sich in eine aktive (sichtbare) Seite übergehen, wenn der Nutzer auf einen Link klickt, und dann im Back-Forward-Cache (nicht sichtbar) gespeichert werden, wenn der Nutzer zu einer anderen Seite navigiert. Die Seite wird dabei nicht gelöscht. Später in diesem Artikel werfen wir einen Blick auf die neuen Properties, mit denen Erweiterungen den Status von Seiten besser nachvollziehen können.

Seitentypen
Seitentypen.

Ein Tab kann eine Reihe von vorab gerenderten Seiten (nicht nur eine), eine einzelne aktive (sichtbare) Seite und eine Reihe von im Back-Forward-Cache gespeicherten Seiten enthalten.

Was ändert sich für Entwickler von Erweiterungen?

FrameId == 0

In Chromium bezeichnen wir den obersten Frame bzw. Hauptframe als den äußersten Frame.

Bei Erweiterungen, die davon ausgehen, dass die frameId des äußersten Frames 0 ist (eine frühere Best Practice), können Probleme auftreten. Da ein Tab jetzt mehrere Frames ganz außen haben kann (vorab gerenderte und im Cache gespeicherte Seiten), wird nicht davon ausgegangen, dass es einen einzelnen Frame außerhalb des Tabs gibt. frameId == 0 stellt weiterhin den äußersten Frame der aktiven Seite dar, aber die äußersten Frames anderer Seiten auf demselben Tab sind nicht null. Um dieses Problem zu beheben, wurde das neue Feld frameType hinzugefügt. Weitere Informationen finden Sie im Abschnitt Wie finde ich heraus, ob ein Frame der äußerste Frame ist? dieses Beitrags.

Lebenszyklus von Frames im Vergleich zu Dokumenten

Ein weiteres Konzept, das bei Erweiterungen problematisch ist, ist der Lebenszyklus des Frames. Ein Frame hostet ein Dokument, das mit einer URL verknüpft ist, für die ein Commit durchgeführt wurde. Das Dokument kann sich ändern (z. B. durch Aufrufen), aber die frameId nicht. Daher ist es schwierig, eine Geschehnisse in einem bestimmten Dokument nur mit frameIds in Verbindung zu bringen. Wir führen das Konzept der documentId ein, bei der es sich um eine eindeutige Kennung für jedes Dokument handelt. Wenn ein Frame aufgerufen und ein neues Dokument geöffnet wird, ändert sich die ID. Mit diesem Feld lässt sich ermitteln, wann sich der Lebenszyklusstatus von Seiten (zwischen „Pre-Rendering“, „Aktiv“ oder „Im Cache“) ändert, da er gleich bleibt.

Webnavigationsereignisse

Ereignisse im chrome.webNavigation-Namespace können je nach Lebenszyklus, in dem sie sich befindet, mehrmals auf derselben Seite ausgelöst werden. Weitere Informationen finden Sie unter Wie finde ich heraus, in welchem Lebenszyklus sich eine Seite befindet? und Wie lege ich fest, wann eine Seite wechselt?.

Woher weiß ich, in welchem Lebenszyklus sich die Seite befindet?

Der Typ DocumentLifecycle wurde mehreren Erweiterungs-APIs hinzugefügt, bei denen zuvor frameId verfügbar war. Wenn der Typ DocumentLifecycle in einem Ereignis (z. B. onCommitted) vorhanden ist, gibt sein Wert den Status an, in dem das Ereignis generiert wurde. Sie können Informationen aus den Methoden WebNavigation getFrame() und getAllFrames() jederzeit abfragen, aber die Verwendung des Werts aus dem Ereignis wird immer bevorzugt. Wenn du eine der beiden Methoden verwendest, solltest du beachten, dass sich der Status des Frames zwischen dem Zeitpunkt der Generierung des Ereignisses und der Auflösung der von beiden Methoden zurückgegebenen Promise-Objekte ändern kann.

DocumentLifecycle hat folgende Werte:

  • "prerender" : Dem Nutzer wird derzeit nicht angezeigt, wird aber möglicherweise für den Nutzer vorbereitet.
  • "active": Wird dem Nutzer angezeigt.
  • "cached": Im Back-Forward-Cache gespeichert.
  • "pending_deletion": Das Dokument wird gelöscht.

Wie erkenne ich, ob ein Frame der äußere Rahmen ist?

Bisher haben Erweiterungen möglicherweise geprüft, ob frameId == 0 überprüft wurde, um festzustellen, ob das Ereignis den äußersten Frame betrifft oder nicht. Bei mehreren Seiten auf einem Tab gibt es jetzt mehrere Frames ganz außen, sodass die Definition von frameId problematisch ist. Sie erhalten keine Ereignisse zu einem im Back-Forward-Cache gespeicherten Frame. Bei vorab gerenderten Frames ist frameId jedoch für den äußersten Frame ungleich null. Daher ist die Verwendung von frameId == 0 als Signal, um festzustellen, ob es sich um den äußersten Frame handelt, falsch.

Um dies zu unterstützen, haben wir einen neuen Typ namens FrameType eingeführt. Damit lässt sich jetzt ganz einfach feststellen, ob der Frame tatsächlich der äußerste Frame ist. FrameType hat die folgenden Werte:

  • "outermost_frame": In der Regel als ganzer Frame bezeichnet. Beachten Sie, dass es ein Vielfaches von diesen gibt. Wenn Sie beispielsweise eine vorab gerenderte und eine im Cache gespeicherte Seite haben, hat jede einen äußersten Frame, der als höchster Frame bezeichnet werden kann.
  • "fenced_frame": Für die zukünftige Verwendung reserviert.
  • "sub_frame": In der Regel ein iFrame.

Wir können DocumentLifecycle mit FrameType kombinieren, um festzustellen, ob ein Frame der aktive äußerste Frame ist. Beispiel: js tab.documentLifecycle == “active” && frameType == “outermost_frame”.

Wie behebe ich Probleme mit der Nutzungszeit von Frames?

Wie bereits erwähnt, hostet ein Frame ein Dokument und der Frame kann zu einem neuen Dokument wechseln, aber der frameId ändert sich nicht. Das führt zu Problemen, wenn Sie ein Ereignis nur mit einem frameId empfangen. Wenn Sie die URL des Frames nachschlagen, kann sie sich vom Zeitpunkt des Ereignisses unterscheiden. Dies wird als Problem mit dem Zeitpunkt der Nutzung bezeichnet.

Deshalb haben wir documentId (und parentDocumentId) eingeführt. Die Methode webNavigation.getFrame() macht frameId jetzt optional, wenn eine documentId angegeben wird. documentId ändert sich, wenn ein Frame verwendet wird.

Wie lege ich fest, wann eine Seite gewechselt wird?

Es gibt explizite Signale, um zu bestimmen, wann eine Seite zwischen den Status wechselt.

Sehen wir uns die WebNavigation-Ereignisse an.

Beim ersten Aufrufen einer Seite werden vier Ereignisse in der unten aufgeführten Reihenfolge angezeigt. Beachten Sie, dass diese vier Ereignisse auftreten können, wenn der Status DocumentLifecycle entweder "prerender" oder "active" ist.

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

Dies ist im folgenden Diagramm dargestellt, in dem sich documentId zu "xyz" ändert, wenn die vorab gerenderte Seite zur aktiven Seite wird.

Die Dokument-ID ändert sich, wenn die vorab gerenderte Seite zur aktiven Seite wird.
Der documentId ändert sich, wenn die vorab gerenderte Seite zur aktiven Seite wird.

Wenn eine Seite vom Back-Forward-Cache oder Pre-Rendering in den Status „Aktiv“ wechselt, gibt es drei weitere Ereignisse (wobei DocumentLifecyle den Status "active" hat).

onBeforeNavigate
onCommitted
onCompleted

documentId bleibt gleich wie in den ursprünglichen Ereignissen. Dies ist oben veranschaulicht, wenn documentId == xyz aktiviert wird. Mit Ausnahme des onDOMContentLoaded-Ereignisses werden dieselben Navigationsereignisse ausgelöst, da die Seite bereits geladen wurde.

Wenn Sie Kommentare oder Fragen haben, können Sie diese in der chromium-extensions-Gruppe stellen.