Estensioni di Chrome: estensione dell'API per supportare la navigazione istantanea

Dave Tapuska
Dave Tapuska

TL;DR: L'API Extensions è stata aggiornata per supportare la cache back-forward, precaricando le navigazioni. Scopri di più nella sezione seguente.

Chrome si è impegnato molto per velocizzare la navigazione. Tecnologie di navigazione istantanea come la cache back/forward (spedizione su desktop in Chrome 96) e le regole di speculazione (spedite in Chrome 103) migliorano sia l'esperienza di navigazione che quella successiva. In questo post esploreremo gli aggiornamenti che abbiamo apportato alle API delle 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 quella visibile. Se un utente torna alla pagina precedente, la pagina attiva viene eliminata (Pagina B) e la pagina precedente nella cronologia viene completamente ricostruita (Pagina A). Le estensioni non dovevano preoccuparsi di quale parte del ciclo di vita erano presenti le pagine perché ne esisteva una sola, ovvero lo stato attivo/visibile.

Eliminazione della pagina attiva
Eliminazione della pagina attiva.

Con la cache back-forward e il prerendering, non esiste più una relazione one-to-one tra schede e pagine. Ogni scheda memorizza invece più pagine e la transizione tra gli stati, anziché essere distrutta e ricostruita.

Ad esempio, una pagina potrebbe iniziare la sua vita come pagina sottoposta a prerendering (non visibile), passare a una pagina attiva (visibile) quando l'utente fa clic su un link e poi essere memorizzata nella cache back-forward (non visibile) quando l'utente passa a un'altra pagina, il tutto senza che la pagina venga mai eliminata. Più avanti in questo articolo esamineremo le nuove proprietà esposte per aiutare le estensioni a capire in quale stato si trovano le pagine.

Tipi di pagine
Tipi di pagine.

Tieni presente che una scheda può avere una serie di pagine sottoposte a prerendering (non solo una), una singola pagina attiva (visibile) e una serie di pagine memorizzate nella cache back-forward.

Cosa cambia per gli sviluppatori di estensioni?

ID frame == 0

In Chromium, il frame più in alto/principale è il frame più esterno.

Gli autori di estensioni che presuppongono che il valore di frameId del frame più esterno sia 0 (una best practice precedente) potrebbero riscontrare problemi. Poiché una scheda può ora avere più frame più esterni (pagine sottoposte a prerendering e memorizzate nella cache), l'ipotesi che per una scheda sia presente un unico frame più esterno 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 saranno diversi da zero. Per risolvere questo problema, è stato aggiunto un nuovo campo frameType. Consulta la sezione "Come faccio a determinare se un frame è il frame più esterno?" del post.

Ciclo di vita dei frame e dei documenti

Un altro concetto problematico delle estensioni è il ciclo di vita del frame. Un frame ospita un documento (associato a un URL di impegno). Il documento può cambiare (ad esempio tramite la navigazione), mentre il valore frameId no, quindi è difficile associare solo i frameId agli eventi che si sono verificati in un documento specifico. Stiamo introducendo il concetto di documentId, ovvero un identificatore univoco per ogni documento. Se l'utente naviga in un frame e apre un nuovo documento, l'identificatore cambia. Questo campo è utile per determinare quando lo stato del ciclo di vita delle pagine cambia (tra prerendering/attiva/memorizzata nella cache) perché rimane lo stesso.

Eventi di navigazione sul web

Gli eventi nello spazio dei nomi chrome.webNavigation possono essere attivati più volte sulla stessa pagina, a seconda del ciclo di vita in cui si trovano. Consulta le sezioni "Come faccio a stabilire in quale ciclo di vita si trova la pagina?" e "Come faccio a stabilire in quali circostanze viene eseguita la transizione di una pagina?".

Come si indica il ciclo di vita della pagina?

Il tipo DocumentLifecycle è stato aggiunto a una serie di API di estensioni in cui frameId era precedentemente disponibile. Se il tipo DocumentLifecycle è presente in un evento (ad esempio onCommitted), il suo valore corrisponde allo 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 dei due metodi, tieni presente che lo stato del frame potrebbe cambiare tra il momento in cui è stato generato l'evento e il momento in cui le promesse vengono restituite con entrambi i metodi.

Il campo DocumentLifecycle ha i seguenti valori:

  • "prerender" : attualmente non presentato all'utente, ma è in corso la preparazione per l'eventuale visualizzazione all'utente.
  • "active": attualmente mostrato all'utente.
  • "cached": archiviato nella cache back-forward.
  • "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 che si verifica riguarda o meno il frame più esterno. Con più pagine in una scheda, ora abbiamo più frame più esterni, quindi la definizione di frameId è problematica. Non riceverai mai eventi su un frame memorizzato nella cache back-forward. Tuttavia, per i frame sottoposti a prerendering, 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 facilitare questa operazione, abbiamo introdotto un nuovo tipo denominato FrameType, per cui ora è facile determinare se il frame è effettivamente il frame più esterno. FrameType contiene i seguenti valori:

  • "outermost_frame": solitamente definito frame più in alto. Tieni presente che ce ne sono multipli. Ad esempio, se hai una pagina sottoposta a prerendering e memorizzata nella cache, ognuna ha un frame più esterno che potrebbe essere chiamato frame più alto.
  • "fenced_frame": riservato per un uso futuro.
  • "sub_frame": in genere un iframe.

Possiamo combinare DocumentLifecycle con FrameType e determinare se un frame è il frame più esterno attivo. Ad esempio: js tab.documentLifecycle == “active” && frameType == “outermost_frame”.

Come faccio a risolvere i problemi relativi al tempo di utilizzo dei frame?

Come abbiamo detto in precedenza, un frame ospita un documento e può passare a un nuovo documento, ma l'elemento frameId non cambierà. Questo crea problemi quando ricevi un evento solo con un frameId. Se cerchi l'URL del frame potrebbe essere diverso da quando si è verificato l'evento, si tratta di un problema relativo all'orario di utilizzo.

Per risolvere questo problema, abbiamo introdotto documentId (e parentDocumentId). Il metodo webNavigation.getFrame() rende ora facoltativo frameId se viene fornito un documentId. documentId cambierà ogni volta che navighi in un frame.

Come faccio a stabilire quando avviene la transizione di una pagina?

Esistono indicatori espliciti che determinano 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 indicato di seguito. Tieni presente che questi quattro eventi possono verificarsi con lo stato DocumentLifecycle "prerender" o "active".

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

Questo è illustrato nel diagramma seguente, che mostra il passaggio di documentId a "xyz" quando la pagina sottoposta a prerendering diventa la pagina attiva.

L'ID documento cambia quando la pagina sottoposta a prerendering diventa la pagina attiva
La proprietà documentId cambia quando la pagina sottoposta a prerendering diventa la pagina attiva.

Quando una pagina passa dalla cache back-forward o da prerendering allo stato attivo, si verificano altri tre eventi (ma DocumentLifecyle è "active").

onBeforeNavigate
onCommitted
onCompleted

L'elemento documentId rimarrà invariato negli eventi originali. Questo è illustrato sopra quando documentId == xyz si attiva. Tieni presente che vengono attivati gli stessi eventi di navigazione, ad eccezione dell'evento onDOMContentLoaded perché la pagina è già stata caricata.

Se avete commenti o domande, non esitate a chiedere al gruppo chromium-extensions.