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 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, un singolo tab aveva una sola pagina attiva. Questo 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 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 memorizza più pagine e le pagine passano da uno stato all'altro anziché 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?

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 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 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 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 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 era precedentemente disponibile frameId. 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": memorizzato nella cache Avanti/Indietro.
  • "pending_deletion": il documento viene distrutto.

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 per il frame più esterno o meno. 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ù valori. Ad esempio, se hai pagine pre-elaborate e memorizzate nella cache, ognuna 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 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. 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 la prima navigazione in qualsiasi 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.

Il valore documentId cambia quando la pagina sottoposta a prerendering diventa la pagina attiva
Il valore 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 uguale 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.