Di recente hai visto un avviso come il seguente nella tua Developers Console in Chrome e ti sei chiesto di cosa si trattasse?
(index):34 A Parser-blocking, cross-origin script,
https://paul.kinlan.me/ad-inject.js, is invoked via document.write().
This may be blocked by the browser if the device has poor network connectivity.
La componibilità è una delle grandi potenzialità del web, che ci consente di integrarci facilmente con i servizi creati da terze parti per creare nuovi fantastici prodotti. Uno degli svantaggi della componibilità è che implica una responsabilità condivisa sulla user experience. Se l'integrazione non è ottimale, l'esperienza utente subirà un impatto negativo.
Una causa nota del cattivo rendimento è l'utilizzo di document.write()
all'interno delle pagine,
in particolare per gli utilizzi che iniettano script. Per quanto innocuo possa sembrare, quanto segue può causare problemi reali per gli utenti.
document.write('<script src="https://example.com/ad-inject.js"></script>');
Prima che il browser possa visualizzare una pagina, deve creare la struttura DOM analizzando il markup HTML. Ogni volta che l'analizzatore incontra uno script, deve interrompersi ed eseguirlo prima di poter continuare l'analisi dell'HTML. Se lo script inietta dinamicamente un altro script, l'interprete è costretto ad attendere ancora più a lungo per il download della risorsa, il che può comportare uno o più viaggi di andata e ritorno sulla rete e ritardare il tempo necessario per il primo rendering della pagina
Per gli utenti con connessioni lente, ad esempio 2G, gli script esterni inseriti in modo dinamico tramite document.write()
possono ritardare di decine di secondi la visualizzazione dei contenuti principali delle pagine oppure causare un caricamento insufficiente delle pagine oppure un tempo così lungo che l'utente rinuncia. In base alla misurazione in Chrome, abbiamo appreso che le pagine con script di terze parti inseriti tramite document.write()
impiegano generalmente il doppio a caricarsi rispetto alle altre pagine con connessione 2G.
Abbiamo raccolto i dati di un esperimento sul campo di 28 giorni sull'1% degli utenti stabili di Chrome, limitato agli utenti con connessioni 2G. Abbiamo rilevato che il 7, 6% di tutti i caricamenti di pagine su rete 2G includeva almeno uno script di blocco del parser cross-site inserito tramite document.write()
nel documento di primo livello. A seguito del blocco
del caricamento di questi script, abbiamo riscontrato i seguenti miglioramenti:
- 10% in più di caricamenti di pagine che raggiungono First Contentful Paint (una conferma visiva per l'utente che la pagina si sta caricando correttamente), 25% in più di caricamenti di pagine che raggiungono lo stato di analisi completa e 10% in meno di ricaricamenti suggeriscono una diminuzione della frustrazione degli utenti.
- Riduzione del 21% del tempo medio (oltre un secondo più veloce) fino al primo paint con contenuto
- Riduzione del 38% del tempo medio necessario per analizzare una pagina, che rappresenta un miglioramento di quasi sei secondi e riduce notevolmente il tempo necessario per visualizzare ciò che è importante per l'utente.
Tenendo conto di questi dati, Chrome, a partire dalla versione 55, interviene per conto di tutti gli utenti quando rileviamo questo pattern noto come dannoso modificando il modo in cui document.write()
viene gestito in Chrome (vedi Stato di Chrome).
In particolare, Chrome non eseguirà gli elementi <script>
iniettati tramite
document.write()
quando sono soddisfatte tutte le seguenti condizioni:
- L'utente utilizza una connessione lenta, in particolare quando utilizza il 2G. In futuro, la modifica potrebbe essere estesa ad altri utenti con connessioni lente, ad esempio 3G o Wi-Fi lento.
document.write()
si trova in un documento di primo livello. L'intervento non si applica agli script document.written all'interno degli iframe perché non bloccano il rendering della pagina principale.- Lo script in
document.write()
blocca il parser. Gli script con gli attributi "async
" o "defer
" continueranno a essere eseguiti. - Lo script non è ospitato sullo stesso sito. In altre parole, Chrome non interviene per gli script con un eTLD+1 corrispondente (ad es. uno script ospitato su js.example.org inserito su www.example.org).
- Lo script non è già presente nella cache HTTP del browser. Gli script nella cache non subiranno un ritardo della rete e verranno comunque eseguiti.
- La richiesta della pagina non è un ricaricamento. Chrome non interviene se l'utente ha attivato una ricarica ed eseguirà la pagina normalmente.
Gli snippet di terze parti a volte utilizzano document.write()
per caricare gli script.
Fortunatamente, la maggior parte delle terze parti offre alternative di caricamento asincrono, che consentono di caricare gli script di terze parti senza bloccare la visualizzazione del resto dei contenuti della pagina.
Come faccio a risolvere il problema?
La risposta semplice è: non iniettare script utilizzando document.write()
. Gestiamo un insieme di servizi noti per il supporto del caricatore asincrono che ti invitiamo a continuare a controllare.
Se il tuo provider non è presente nell'elenco e supporta il caricamento di script asincroni, comunicacelo e potremo aggiornare la pagina per aiutare tutti gli utenti.
Se il tuo provider non supporta la possibilità di caricare script in modo asincrono nella tua pagina, ti invitiamo a contattarlo e a comunicarci e comunicargli in che modo sarà interessato.
Se il tuo fornitore ti fornisce uno snippet che include document.write()
, potrebbe essere possibile aggiungere un attributo async
all'elemento script o aggiungere gli elementi script con API DOM come document.appendChild()
o parentNode.insertBefore()
.
Come rilevare quando il tuo sito è interessato
Esistono una serie di criteri che determinano se la limitazione viene applicata, quindi come fai a sapere se ti riguarda?
Rilevamento della connessione 2G di un utente
Per comprendere il potenziale impatto di questa modifica, devi prima capire quanti dei tuoi utenti utilizzeranno il 2G. Puoi rilevare il tipo di rete e la velocità corrente dell'utente utilizzando l'API Network Information disponibile in Chrome e inviare un avviso ai tuoi sistemi di analisi o RUM (Real User Metrics).
if(navigator.connection &&
navigator.connection.type === 'cellular' &&
navigator.connection.downlinkMax <= 0.115) {
// Notify your service to indicate that you might be affected by this restriction.
}
Rilevare gli avvisi in Chrome DevTools
A partire da Chrome 53, DevTools emette avvisi per le istruzioni document.write()
problematiche. Nello specifico, se una richiesta document.write()
soddisfa i criteri da 2 a 5
(Chrome ignora i criteri di connessione quando invia questo avviso), l'avviso sarà simile a:
È fantastico vedere gli avvisi in Chrome DevTools, ma come li rilevi su larga scala? Puoi controllare le intestazioni HTTP inviate al tuo server quando avviene l'intervento.
Controlla le intestazioni HTTP nella risorsa dello script
Quando uno script inserito tramite document.write
è stato bloccato, Chrome invia la seguente intestazione alla risorsa richiesta:
Intervention: <https://shorturl/relevant/spec>;
Quando viene rilevato uno script inserito tramite document.write
e potrebbe essere bloccato in diverse circostanze, Chrome potrebbe inviare:
Intervention: <https://shorturl/relevant/spec>; level="warning"
L'intestazione di intervento verrà inviata nell'ambito della richiesta GET per lo script (in modo asincrono in caso di intervento effettivo).
Che cosa ci riserva il futuro?
Il piano iniziale è di eseguire questo intervento quando rileviamo che i criteri sono soddisfatti. Abbiamo iniziato mostrando solo un avviso nella Console per gli sviluppatori in Chrome 53. (la versione beta è stata rilasciata a luglio 2016. Prevediamo che la versione stabile sarà disponibile per tutti gli utenti a settembre 2016.
Interverremo per bloccare gli script iniettati per gli utenti 2G in via sperimentale a partire da Chrome 54, che dovrebbe essere disponibile in una versione stabile per tutti gli utenti a metà ottobre 2016. Per ulteriori aggiornamenti, consulta la voce dello stato di Chrome.
Nel tempo, prevediamo di intervenire quando la connessione di un utente è lenta (ad es.3G o Wi-Fi lento). Segui questa voce dello stato di Chrome.
Vuoi saperne di più?
Per saperne di più, consulta queste risorse aggiuntive:
- Specifiche dell'intervento document.write() e dei relativi loop di feedback
- Stato di Chrome (intervento per gli utenti su 2G)
- Stato di Chrome (intervento per gli utenti con connessioni effettivamente lente)
- Documento di progettazione
- Ulteriori motivazioni alla base di questo impegno
- Intent di blink-dev per implementare il thread