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 e il precaricamento delle navigazioni. Scopri di più nella sezione seguente.

Chrome si sta adoperando 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 delle estensioni del browser per adeguarsi a questi nuovi flussi di lavoro.

Comprendere i 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 eliminata (Pagina B) mentre la pagina precedente della cronologia viene ricostruita completamente (Pagina A). Le estensioni non dovevano preoccuparsi di quale parte del ciclo di vita riguardassero le pagine perché ne esisteva una sola per una scheda, lo stato attivo/visibile.

Sfratto della pagina attiva
Espulsione della pagina attiva.

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 esaminare le nuove proprietà esposte per aiutare le estensioni a capire in quali pagine di stato si trovano.

Tipi di pagine
Tipi di pagine
.

Tieni presente che una scheda può avere una serie di pagine pre-renderizzate (non solo una), una singola pagina attiva (visibile) e una serie di pagine memorizzate nella cache di Avanti/Indietro.

Cosa cambia per gli sviluppatori di estensioni?

ID frame == 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 esterni (pagine pre-renderizzate e memorizzate nella cache), l'assunto che esista un singolo frame esterno per una scheda è errato. 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 e dei documenti

Un altro concetto problematico con le estensioni è il ciclo di vita del frame. Un frame ospita un documento (che è associato a un URL di cui è stato eseguito il commit). 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 viene visualizzato un frame e si 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 web

Gli eventi nello spazio dei nomi chrome.webNavigation possono attivarsi più volte sulla stessa pagina a seconda del ciclo di vita in cui si trova. 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 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 visualizzato dall'utente.
  • "cached": archiviata nella cache back-forward.
  • "pending_deletion": il documento viene distrutto.

Come faccio a determinare se un frame è quello 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 esterni, quindi la definizione di frameId è problematica. Non riceverai mai eventi relativi a un frame memorizzato nella cache con opzione Indietro/Avanti. 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 sottoposte a prerendering e memorizzate nella cache, ognuna ha un frame più esterno che potrebbe essere chiamato frame più in alto.
  • "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 faccio a risolvere i problemi relativi all'ora di utilizzo con le cornici?

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. L'elemento documentId cambia ogni volta che esplori 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 la 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

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

Il valore documentId cambia quando la pagina sottoposta a prerendering diventa la pagina attiva
documentId cambia quando la pagina sottoposta a prerendering diventa la pagina attiva.

Quando una pagina passa dalla cache back-forward o dal prerendering allo stato attivo, vengono generati altri tre eventi (ma con DocumentLifecyle corrispondente a "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.