TL;DR: l'API Extensions è stata aggiornata per supportare la cache back-forward e il precaricamento delle navigazioni. Scopri di più nella sezione seguente.
Chrome si impegna a fondo per rendere la navigazione veloce. Le tecnologie di navigazione istantanea come la cache back-forward (implementata su computer in Chrome 96) e le regole di speculazione (implementate in Chrome 103) migliorano sia l'esperienza di navigazione avanti che quella di navigazione indietro. In questo post esploreremo gli aggiornamenti che abbiamo apportato alle API di estensioni del browser per supportare questi nuovi flussi di lavoro.
Informazioni sui tipi di pagine
Prima dell'introduzione della cache back-forward e del prerendering, una singola scheda aveva una sola pagina attiva. Era sempre quello visibile. Se un utente torna alla pagina precedente, la pagina attiva viene distrutta (pagina B) e la pagina precedente nella cronologia viene ricostruita completamente (pagina A). Le estensioni non dovevano preoccuparsi di quale parte del ciclo di vita si trovavano le pagine del ciclo di vita, perché ne esisteva solo una per ogni scheda, ovvero lo stato attivo/visibile.
Con la cache back-forward e il prerendering, non esiste più un rapporto uno a uno tra schede e pagine. Ora, ogni scheda archivia più pagine e pagine di transizione tra gli stati, invece di essere distrutte e ricostruite.
Ad esempio, una pagina potrebbe iniziare la sua vita come pagina pre-visualizzata (non visibile), passare a una pagina attiva (visibile) quando l'utente fa clic su un link e poi essere memorizzata nella cache di navigazione (non visibile) quando l'utente passa a un'altra pagina, il tutto senza che la pagina venga mai distrutta. Più avanti in questo articolo esamineremo le nuove proprietà esposte per aiutare le estensioni a capire a quale stato si trovano le pagine.
Tieni presente che una scheda può avere una serie di pagine sottoposte a prerendering (non una sola), una singola pagina attiva (visibile) e una serie di pagine memorizzate nella cache Indietro/Avanti.
Cosa cambia per gli sviluppatori di estensioni?
FrameId == 0
In Chromium, il frame principale/superiore è il frame più esterno.
Gli autori di estensioni che presumono che frameId
del frame più esterno sia 0 (una best practice precedente) potrebbero riscontrare problemi.
Poiché ora una scheda può avere più frame più esterni (pagine prerenderizzate e memorizzate nella cache), l'ipotesi che ci sia un singolo frame più esterno per una scheda non è corretta. frameId == 0
continuerà a rappresentare il frame più esterno della pagina attiva, ma i frame più esterni delle altre pagine nella stessa scheda non saranno nulli. Per risolvere il problema è stato aggiunto un nuovo campo frameType. Consulta la sezione "Come faccio a determinare se un frame è il frame più esterno?" di questo post.
Ciclo di vita dei frame rispetto ai documenti
Un altro concetto problematico con le estensioni è il ciclo di vita del frame. Un frame ospita un documento (associato a un URL impegnato). Il documento può cambiare (ad esempio durante la navigazione), ma frameId no, pertanto è difficile associare un evento a un documento specifico solo con frameId. Stiamo introducendo il concetto di documentId, che è un identificatore univoco per ogni documento. Se un frame viene esplorato e apre un nuovo documento, l'identificatore cambia. Questo campo è utile per determinare quando le pagine cambiano stato nel ciclo di vita (tra prerendering/attivo/in cache) perché rimane invariato.
Eventi di navigazione sul web
Gli eventi nello spazio dei nomi chrome.webNavigation
possono essere attivati più volte nella stessa pagina a seconda del ciclo di vita in cui si trovano. Consulta le sezioni "Come faccio a capire in quale ciclo di vita si trova la pagina?" e "Come faccio a determinare quando una pagina passa da uno stato all'altro?".
Come faccio a capire in quale fase del ciclo di vita si trova la pagina?
Il tipo DocumentLifecycle
è stato aggiunto a una serie di API di estensioni in cui frameId
era
disponibile in precedenza. Se il tipo DocumentLifecycle
è presente in un evento
(ad esempio onCommitted
),
il suo valore è lo stato in cui è stato generato l'evento. Puoi sempre eseguire query sulle informazioni dei metodi WebNavigation
getFrame()
e getAllFrames()
, ma è sempre preferibile utilizzare il valore dell'evento. Se utilizzi uno di questi metodi, tieni presente che lo stato del frame potrebbe cambiare tra il momento in cui è stato generato l'evento e la risoluzione delle promesse restituite da entrambi i metodi.
DocumentLifecycle
ha i seguenti valori:
"prerender
": non viene attualmente presentato all'utente, ma è in preparazione per essere eventualmente mostrato."active"
: attualmente mostrata all'utente."cached"
: memorizzato nella cache Avanti/Indietro."pending_deletion"
: il documento è in fase di eliminazione.
Come faccio a determinare se un frame è il frame più esterno?
In precedenza, le estensioni potrebbero aver controllato se frameId == 0
per determinare se l'evento si verifica o meno per il frame più esterno. Con più pagine
in una scheda ora abbiamo più frame esterni, quindi la definizione di frameId
è problematica. Non riceverai mai eventi relativi a un frame memorizzato nella cache back-forward. Tuttavia, per i frame pre-renderizzati, frameId
sarà diverso da zero per il frame più esterno. Pertanto, l'utilizzo di frameId == 0
come indicatore per determinare se si tratta del frame più esterno non è corretto.
Per aiutarti, abbiamo introdotto un nuovo tipo chiamato
FrameType
in modo che sia facile determinare se il frame è effettivamente il frame più esterno.
FrameType
ha i seguenti valori:
"outermost_frame"
: in genere indicato come frame più alto. Tieni presente che esistono più di questi valori. Ad esempio, se hai pagine pre-elaborate e memorizzate nella cache, ciascuna ha un frame più esterno che potrebbe essere chiamato frame principale."fenced_frame"
: riservato per l'uso futuro."sub_frame"
: in genere un iframe.
Possiamo combinare DocumentLifecycle
con FrameType
e determinare se un frame è
il frame esterno attivo. Ad esempio: tab.documentLifecycle === “active” && frameType === “outermost_frame”
.
Come si risolvono i problemi relativi al tempo di utilizzo dei frame?
Come abbiamo detto sopra, un frame ospita un documento e può passare a un nuovo
documento, ma frameId
non cambierà. Ciò crea problemi quando ricevi un evento con solo un frameId
. Se cerchi l'URL
del frame, potrebbe essere diverso da quello al momento dell'evento. Si tratta di un
problema di momento di utilizzo.
Per risolvere il problema, abbiamo introdotto documentId
(e parentDocumentId
).
Il metodo webNavigation.getFrame()
ora rende facoltativo frameId
se viene fornito documentId
. Il valore documentId
cambia ogni volta che viene visualizzato un frame.
Come faccio a determinare quando avviene una transizione di pagina?
Esistono indicatori espliciti per determinare quando una pagina passa da uno stato all'altro.
Diamo un'occhiata agli eventi WebNavigation
.
Per una prima navigazione in una pagina, vedrai quattro eventi nell'ordine
elencato di seguito. Tieni presente che questi quattro eventi potrebbero verificarsi con lo stato DocumentLifecycle
pari a "prerender"
o "active"
.
onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted
Questo è illustrato nel diagramma seguente, che mostra il passaggio da documentId
a "xyz"
quando la pagina pre-renderizzata diventa la pagina attiva.
Quando una pagina passa dalla cache back-forward o dal prerendering allo
stato attivo, ci sono altri tre eventi (ma DocumentLifecyle
è "active"
).
onBeforeNavigate
onCommitted
onCompleted
documentId
rimarrà invariato rispetto agli eventi originali. Questo è illustrato sopra quando si attiva documentId
== xyz. Tieni presente che vengono attivati gli stessi eventi di navigazione, ad eccezione dell'evento onDOMContentLoaded
, perché la pagina è già stata caricata.
Per eventuali commenti o domande, non esitare a chiedere nel gruppo chromium-extensions.