TL;DR: interfejs Extensions API został zaktualizowany, aby obsługiwać pamięć podręczną stanu strony internetowej i wstępne wczytywanie nawigacji. Więcej informacji znajdziesz poniżej.
Pracujemy nad tym, aby nawigacja w Chrome była szybka. Technologie błyskawicznej nawigacji, takie jak pamięć podręczna stanu strony internetowej (wprowadzona na komputerach w Chrome 96) i reguły spekulacji (wprowadzone w Chrome 103), poprawiają zarówno wrażenia z przechodzenia do poprzedniej i następnej strony. W tym poście omówimy zmiany, które wprowadziliśmy w interfejsach API rozszerzeń przeglądarki, aby uwzględnić te nowe procesy.
Typy stron
Przed wprowadzeniem pamięci podręcznej stanu strony internetowej i prerenderowania każda karta miała tylko jedną aktywną stronę. Ta opcja była zawsze widoczna. Jeśli użytkownik wróci do poprzedniej strony, aktywna strona zostanie zniszczona (strona B), a poprzednia strona w historii zostanie całkowicie odtworzona (strona A). Rozszerzenia nie musiały się martwić, w której fazie cyklu życia znajdują się strony, ponieważ dla każdej karty był tylko jeden stan: aktywny lub widoczny.
Dzięki pamięci podręcznej stanu strony internetowej i prerenderowaniu nie ma już relacji jeden do jednego między kartami a stronami. Teraz każda karta przechowuje wiele stron, a strony przechodzą między stanami, zamiast być usuwane i odtwarzane.
Na przykład strona może być najpierw renderowana (niewidoczna), potem, gdy użytkownik kliknie link, staje się aktywna (widoczna), a potem, gdy użytkownik przejdzie na inną stronę, jest przechowywana w pamięci podręcznej stanu strony internetowej (niewidoczna). W dalszej części tego artykułu omówimy nowe właściwości, które pomogą rozszerzeniom określić, w jakim stanie są strony.
Pamiętaj, że karta może zawierać serię wyrenderowanych stron (nie tylko jedną), jedną aktywną (widoczną) stronę oraz serię stron z pamięci podręcznej z funkcją Wstecz/Do przodu.
Co się zmieni dla twórców rozszerzeń?
FrameId == 0
W Chromium ramka górna/główna jest nazywana zewnętrzną.
Autorzy rozszerzeń, którzy zakładają, że frameId
ramki zewnętrznej ma wartość 0 (wcześniejsza sprawdzona metoda), mogą napotkać problemy.
Ponieważ karta może mieć teraz wiele zewnętrznych ramek (stron wstępnie wyrenderowanych i przechowywanych w pamięci podręcznej), założenie, że karta ma jedną zewnętrzną ramkę, jest nieprawidłowe. frameId == 0
nadal będzie reprezentować najbardziej zewnętrzny element aktywnej strony, ale najbardziej zewnętrzne elementy innych stron na tej samej karcie będą inne niż 0. Aby rozwiązać ten problem, dodaliśmy nowe pole frameType. Przeczytaj sekcję „Jak określić, czy ramka jest najbardziej zewnętrzną?” tego wpisu.
Cykl życia ramek a dokumenty
Innym problemem związanym z rozszerzeniami jest cykl życia ramki. Ramka zawiera dokument (powiązany z zaakceptowanym adresem URL). Dokument może się zmieniać (np. podczas nawigacji), ale frameId pozostanie niezmieniony. Trudno więc powiązać coś, co dzieje się w konkretnym dokumencie, tylko z frameId. Wprowadzamy pojęcie documentId, które jest unikalnym identyfikatorem każdego dokumentu. Jeśli nastąpi przejście do ramki i otworzy się nowy dokument, identyfikator się zmieni. To pole jest przydatne do określania, kiedy strony zmieniają stan cyklu życia (między stanem wstępnym wyrenderowania, aktywnym i w pamięci podręcznej), ponieważ pozostaje ono takie samo.
Zdarzenia nawigacji w internecie
Zdarzenia w przestrzeni nazw chrome.webNavigation
mogą być wywoływane wielokrotnie na tej samej stronie w zależności od cyklu życia. Zapoznaj się z sekcjami „Jak sprawdzić, na jakim etapie cyklu życia znajduje się strona?” i „Jak określić, kiedy nastąpi przejście strony?”.
Jak mogę sprawdzić, na jakim etapie cyklu życia znajduje się strona?
Dodano typ DocumentLifecycle
do kilku interfejsów API rozszerzeń, w których wcześniej dostępny był typ frameId
. Jeśli zdarzenie ma typ DocumentLifecycle
(np. onCommitted
), jego wartość to stan, w którym zostało wygenerowane. Zawsze możesz wysłać zapytanie o informacje z metod WebNavigation
getFrame()
i getAllFrames()
, ale zalecamy korzystanie z wartości z zdarzenia. Jeśli używasz którejś z tych metod, pamiętaj, że stan ramki może się zmienić między momentem wygenerowania zdarzenia a rozwiązaniem obietnic zwracanych przez obie metody.
Wartości DocumentLifecycle
:
"prerender
”: nie jest obecnie wyświetlany użytkownikowi, ale jest przygotowywany do wyświetlenia."active"
: obecnie wyświetlany użytkownikowi."cached"
: przechowywane w pamięci podręcznej stanu strony internetowej."pending_deletion"
: dokument jest niszczony.
Jak mogę określić, czy ramka jest ramką zewnętrzną?
Wcześniej rozszerzenia mogły sprawdzać, czy frameId == 0
, aby określić, czy zdarzenie dotyczy zewnętrznego elementu ramki. W przypadku wielu stron na karcie mamy teraz wiele zewnętrznych ramek, więc definicja frameId jest problematyczna. Nigdy nie otrzymasz zdarzeń dotyczących ramki w pamięci podręcznej stanu strony internetowej. Jednak w przypadku wstępnie wyrenderowanych klatek wartość frameId
będzie różna od 0 w przypadku najbardziej zewnętrznej ramki. Dlatego użycie frameId == 0
jako sygnału do określenia, czy jest to najbardziej zewnętrzny element, jest nieprawidłowe.
Aby ułatwić to zadanie, wprowadziliśmy nowy typ o nazwie FrameType
, dzięki czemu teraz łatwo określić, czy dany element jest rzeczywiście najbardziej zewnętrznym elementem.
Wartości FrameType
:
"outermost_frame"
: zwykle określana jako najwyższa klatka. Pamiętaj, że są one wielokrotnościami. Jeśli na przykład masz strony z zabezpieczonymi wcześniej i przechowywanymi w pamięci podręcznej, każda z nich ma zewnętrzną ramkę, którą można nazwać najwyższą ramką."fenced_frame"
: zarezerwowany do użycia w przyszłości."sub_frame"
: zwykle element iframe.
Możemy połączyć DocumentLifecycle
z FrameType
i określić, czy klatka jest aktywną zewnętrzną klatką. Na przykład: tab.documentLifecycle === “active” && frameType === “outermost_frame”
Jak rozwiązać problemy z czasem wyświetlania w przypadku ramek?
Jak już wspomnieliśmy, ramka może wyświetlać dokument i przechodzić do nowego dokumentu, ale frameId
nie ulegnie zmianie. Powoduje to problemy, gdy otrzymasz zdarzenie z tylko frameId
. Jeśli sprawdzisz adres URL ramki, może on być inny niż w momencie wystąpienia zdarzenia. Jest to problem z czasem użycia.
Aby rozwiązać ten problem, wprowadziliśmy documentId
(oraz parentDocumentId
). Metoda webNavigation.getFrame() sprawia, że frameId
jest opcjonalny, jeśli podano wartość documentId
. Wartość documentId
zmienia się, gdy użytkownik przewija film.
Jak określić, kiedy następuje przejście na inną stronę?
Istnieją wyraźne sygnały, które określają, kiedy strona przechodzi między stanami.
Przyjrzyjmy się zdarzeniom WebNavigation
.
Podczas pierwszej wizyty na dowolnej stronie zobaczysz 4 zdarzenia w kolejności podanej poniżej. Pamiętaj, że te 4 zdarzenia mogą wystąpić, gdy stan DocumentLifecycle
ma wartość "prerender"
lub "active"
.
onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted
Pokazuje to diagram poniżej, na którym widać, jak documentId
zmienia się na "xyz"
, gdy wstępnie wyrenderowana strona staje się aktywna.
Gdy strona przechodzi z pamięci podręcznej stanu strony internetowej lub prerenderowania do stanu aktywnego, występują 3 dodatkowe zdarzenia (ale DocumentLifecyle
jest zastąpione przez "active"
).
onBeforeNavigate
onCommitted
onCompleted
Wartość documentId
pozostanie taka sama jak w pierwotnych zdarzeniach. Powyższe przykłady pokazują, co się dzieje, gdy documentId
= xyz. Pamiętaj, że te same zdarzenia nawigacyjne są wywoływane, z wyjątkiem zdarzenia onDOMContentLoaded
, ponieważ strona została już załadowana.
Jeśli masz uwagi lub pytania, skontaktuj się z nami w grupie chromium-extensions.