Rozszerzenia do Chrome: interfejs API rozszerzający o obsługę natychmiastowej nawigacji

Dave Tapuska
Dave Tapuska

TL;DR: zaktualizowaliśmy interfejs Extensions API, aby obsługiwać pamięć podręczną stanu strony internetowej i wstępne wczytywanie nawigacji. Więcej informacji znajdziesz poniżej.

Intensywnie pracujemy nad tym, by nawigacja w Chrome była szybsza. Technologie natychmiastowej nawigacji, takie jak pamięć podręczna stanu strony internetowej (wysyłana na komputery w Chrome 96) i reguły spekulacyjne (dostępne w Chrome 103), ułatwiają korzystanie z tej technologii zarówno w przyszłości, jak i w przyszłości. W tym poście omówimy aktualizacje interfejsów API rozszerzeń do przeglądarek, aby dostosować je do nowych przepływów pracy.

Omówienie typów stron

Przed wprowadzeniem pamięci podręcznej stanu strony internetowej i renderowaniem wstępnym każda karta miała tylko jedną aktywną stronę. Ta zawsze była widoczna. Jeśli użytkownik wróci na poprzednią stronę, aktywna strona zostanie zniszczona (strona B), a poprzednia strona w historii zostanie całkowicie zrekonstruowana (strona A). Rozszerzenia nie musiały się martwić o to, w której części strony cyklu życia się znajdują, ponieważ na karcie była tylko jedna (aktywna/widoczna).

Usunięcie aktywnej strony
Usunięcie aktywnej strony

W przypadku pamięci podręcznej stanu strony internetowej i renderowania wstępnego nie ma już związku między kartami a stronami. Obecnie każda karta zawiera wiele stron i stron przechodzenia między stanami, zamiast być niszczona czy zrekonstruowana.

Strona może na przykład być wstępnie renderowana (niewidoczna) po kliknięciu linku przez użytkownika, a potem zapisywana w pamięci podręcznej stanu strony internetowej (niewidoczna), gdy użytkownik przejdzie na inną stronę – a wszystko to bez jej zniszczenia. W dalszej części tego artykułu przyjrzymy się nowym usługom, które ułatwiają rozszerzeniom określenie, w jakim formacie znajdują się strony ze stanem faktycznym.

Typy stron
Typy stron.

Pamiętaj, że karta może zawierać serię wstępnie wyrenderowanych stron (nie tylko jedną), 1 aktywną (widoczną) stronę oraz serię stron w pamięci podręcznej stanu strony internetowej.

Co się zmieni dla deweloperów rozszerzeń?

FrameId == 0

W Chromium górna/główną klatkę nazywamy najbardziej zewnętrzną.

Problemy mogą występować u autorów rozszerzeń, którzy zakładają, że frameId najbardziej zewnętrznej ramki wynosi 0 (zgodnie z wcześniejszą sprawdzoną metodą). Karta może teraz mieć wiele najbardziej zewnętrznych ramek (stron wyrenderowanych i zapisanych w pamięci podręcznej), dlatego Założenie, że istnieje jedna najbardziej zewnętrzna ramka, jest nieprawidłowe. frameId == 0 nadal będzie reprezentować najbardziej zewnętrzną ramkę aktywnej strony, ale najbardziej zewnętrzne ramki innych stron w tej samej karcie będą inne niż zero. Aby rozwiązać ten problem, dodano nowe pole frameType. Zapoznaj się z sekcją „Jak ustalić, czy ramka jest najbardziej zewnętrzną?” w tym poście.

Cykl życia ramek a dokumenty

Innym problemem, który powoduje problemy z rozszerzeniami, jest cykl życia ramki. Ramka przechowuje dokument (powiązany z zatwierdzonym adresem URL). Dokument może się zmieniać (np. podczas nawigacji), ale element frameId nie zmienia. Dlatego trudno jest powiązać zdarzenia w konkretnym dokumencie tylko za pomocą parametrów frameId. Wprowadzamy pojęcie documentId, które jest unikalnym identyfikatorem każdego dokumentu. Identyfikator zmienia się, gdy przejdziesz do ramki i otworzy się nowy dokument. To pole przydaje się do określania, kiedy strony zmieniają swój stan cyklu życia (między wstępnie renderowaniem/aktywnym/z pamięci podręcznej), ponieważ pozostaje bez zmian.

Zdarzenia nawigacji w internecie

Zdarzenia w przestrzeni nazw chrome.webNavigation mogą być uruchamiane wielokrotnie na tej samej stronie w zależności od cyklu życia, w którym się ona znajduje. Zapoznaj się z sekcjami „Jak stwierdzić, w jakim cyklu życia znajduje się strona?” i „Jak określić, kiedy strona się zmienia?”.

Jak określić cykl życia strony?

Typ DocumentLifecycle został dodany do wielu interfejsów API rozszerzeń, w których wcześniej dostępna była opcja frameId. Jeśli w zdarzeniu (np. onCommitted) występuje typ DocumentLifecycle, jego wartością jest stan, w którym to zdarzenie zostało wygenerowane. Zawsze możesz tworzyć zapytania o informacje z metod WebNavigation getFrame() i getAllFrames(), ale zawsze zalecamy używanie wartości ze zdarzenia. Jeśli używasz jednej z tych metod, pamiętaj, że stan ramki może się zmienić w czasie między wygenerowaniem zdarzenia a możliwością zwrócenia obietnicy za pomocą obu metod.

DocumentLifecycle ma te wartości:

  • "prerender”: obecnie nie prezentowane użytkownikowi, ale przygotowującym się do wyświetlania użytkownikowi.
  • "active": wyświetlane obecnie użytkownikowi.
  • "cached": w pamięci podręcznej stanu strony internetowej.
  • "pending_deletion": dokument jest niszczony.

Jak mogę sprawdzić, czy klatka jest najbardziej zewnętrzną?

Wcześniej rozszerzenia mogły sprawdzać, czy frameId == 0, aby określić, czy zdarzenie występuje w skrajnej klatce, czy nie. Gdy na jednej karcie znajduje się wiele stron, mamy teraz wiele najbardziej zewnętrznych ramek, więc definicja pola frameId jest problematyczna. Nigdy nie będziesz otrzymywać zdarzeń dotyczących ramki Wstecz/Dalej. Jednak w przypadku wyrenderowanych wstępnie klatek dla najbardziej zewnętrznej klatki parametr frameId będzie miał wartość większą niż 0. Dlatego użycie frameId == 0 jako sygnału do określenia, czy jest to najbardziej zewnętrzna ramka, jest nieprawidłowe.

Aby Ci w tym pomóc, wprowadziliśmy nowy typ o nazwie FrameType. Dzięki temu teraz łatwo sprawdzisz, czy dana ramka jest rzeczywiście najbardziej zewnętrzną. FrameType ma następujące wartości:

  • "outermost_frame": zwykle nazywana najwyższą klatką. Pamiętaj, że jest ich wiele. Jeśli np. masz strony renderowane wstępnie i w pamięci podręcznej, każda z nich zawiera najbardziej zewnętrzną ramkę, którą można nazwać ramką najwyższego poziomu.
  • "fenced_frame": zarezerwowane do wykorzystania w przyszłości.
  • "sub_frame": zwykle element iframe.

Możemy połączyć parametry DocumentLifecycle z parametrem FrameType i określić, czy dana ramka jest aktywną klatką zewnętrzną. Na przykład: js tab.documentLifecycle == “active” && frameType == “outermost_frame”

Jak rozwiązać problemy z czasem użytkowania ramek?

Jak wspomnieliśmy powyżej, ramka zawiera dokument, a ramka może przejść do nowego dokumentu, ale frameId się nie zmieni. Powoduje to problemy, gdy odbierasz zdarzenie tylko z wartością frameId. Jeśli wyszukasz adres URL klatki, może się on różnić od daty wystąpienia zdarzenia. Jest to tzw. problem z czasem użycia.

Aby rozwiązać ten problem, wprowadziliśmy funkcje documentId (i parentDocumentId). Metoda webNavigation.getFrame() sprawia, że frameId jest teraz opcjonalny, jeśli podany jest documentId. Wartość documentId będzie się zmieniać za każdym razem, gdy poruszasz się po klatce.

Jak mogę określić, kiedy strona jest przenoszona?

Istnieją wyraźne sygnały, które określają, kiedy strona przechodzi między stanami.

Przyjrzyjmy się zdarzeniom WebNavigation.

Przy pierwszej nawigacji na dowolnej stronie widoczne są 4 zdarzenia wymienione poniżej. Pamiętaj, że te 4 zdarzenia mogą mieć stan DocumentLifecycle o wartości "prerender" lub "active".

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

Widać to na diagramie poniżej. Parametr documentId zmienia się w "xyz", gdy wstępnie renderowana strona staje się aktywną.

Identyfikator dokumentu zmienia się, gdy wstępnie renderowana strona stanie się aktywną stroną.
Wartość documentId zmienia się, gdy wstępnie renderowana strona staje się aktywną.

Gdy strona przejdzie z pamięci podręcznej stanu strony internetowej lub renderowania wstępnego w stan aktywny, pojawią się 3 kolejne zdarzenia (ale DocumentLifecyle będzie mieć wartość "active").

onBeforeNavigate
onCommitted
onCompleted

documentId pozostanie bez zmian co w pierwotnych wydarzeniach. Pokazano to powyżej, gdy aktywuje się documentId == xyz. Uruchamiają się te same zdarzenia nawigacji oprócz zdarzenia onDOMContentLoaded, które wynika z tego, że strona została już wczytana.

Jeśli masz jakieś komentarze lub pytania, możesz je zadać na stronie chromium-extensions.