Tag script: asincrono e differisci


548

Ho un paio di domande sugli attributi asynce deferper il <script>tag che a mio modo di vedere funzionano solo nei browser HTML5.

Uno dei miei siti ha due file JavaScript esterni che attualmente si trovano appena sopra il </body>tag; il primo è proveniente da google e il secondo è uno script esterno locale.

Rispetto alla velocità di caricamento del sito

  1. C'è qualche vantaggio nell'aggiungere asyncai due script che ho in fondo alla pagina?

  2. Ci sarebbe qualche vantaggio nell'aggiungere l' asyncopzione ai due script e metterli in cima alla pagina nella <head>?

  3. Significherebbe che scaricano mentre la pagina si carica?
  4. Presumo che ciò causerebbe ritardi per i browser HTML4, ma accelererebbe il caricamento della pagina per i browser HTML5?

utilizzando <script defer src=...

  1. Caricare i due script all'interno <head>con l'attributo avrebbe deferlo stesso effetto di avere gli script prima </body>?
  2. Ancora una volta suppongo che ciò rallenterebbe i browser HTML4.

utilizzando <script async src=...

Se ho due script con asyncabilitato

  1. Avrebbero scaricato contemporaneamente?
  2. O uno alla volta con il resto della pagina?
  3. L'ordine degli script diventa quindi un problema? Ad esempio uno script dipende dall'altro, quindi se uno si scarica più velocemente, il secondo potrebbe non essere eseguito correttamente ecc.

Infine, sono meglio lasciare le cose come sono fino a quando HTML5 non viene più comunemente usato?


5
asyncè nuovo (ish), ma deferfa parte di IE da IE4. deferè stato aggiunto ad altri browser molto più recentemente, ma le versioni precedenti di quei browser tendono a rimanere molto meno.
Alohci,

3
Ora, HTML5 è diventato molto popolare!
settembre08

2
deferè come posizionare gli script in fondo all'HTML, che è stato comune per molti anni.
vsync,

1
@vsync non è necessariamente vero, il browser scaricherà il JS con il tag di differimento quando analizza il tag di script, ma rinvierà l'esecuzione fino a subito prima di DOMContentLoaded. Il download è non bloccante. Il posizionamento nella parte inferiore dell'HTML ritarderà il download e l'esecuzione del JS fino alla creazione del DOM, ma si dovrà comunque attendere un ulteriore ritardo in attesa del download.
Brad Frost,

@BradFrost - A mio avviso, il download sta bloccando, nel senso che sta prendendo larghezza di banda Internet, e per quelli con una connessione lenta, vedo come imperativo caricare prima il documento e solo allora, quando è stato reso, iniziare a scaricare file javascript . Questo è vero nei casi in cui il contenuto non è strettamente accoppiato a javascript per il rendering di tutto (come SPA )
vsync

Risposte:


406

Conserva i tuoi script prima </body>. Async può essere usato con gli script che si trovano lì in alcune circostanze (vedi discussione sotto). Il differimento non farà molta differenza per gli script che si trovano lì perché il lavoro di analisi DOM è stato praticamente già fatto comunque.

Ecco un articolo che spiega la differenza tra asincrono e differire: http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/ .

Il tuo HTML verrà visualizzato più rapidamente nei browser più vecchi se mantieni gli script alla fine del corpo prima </body>. Pertanto, per preservare la velocità di caricamento nei browser meno recenti, non si desidera metterli altrove.

Se il tuo secondo script dipende dal primo script (ad es. Il tuo secondo script utilizza jQuery caricato nel primo script), non puoi renderli asincroni senza codice aggiuntivo per controllare l'ordine di esecuzione, ma puoi farli differire perché gli script di differimento ancora essere eseguito in ordine, solo dopo che il documento è stato analizzato. Se hai quel codice e non hai bisogno che gli script vengano eseguiti immediatamente, puoi renderli asincroni o differire.

È possibile inserire gli script nel <head>tag e impostarli su defere il caricamento degli script verrà rinviato fino a quando il DOM non sarà analizzato e ciò consentirà una rapida visualizzazione della pagina nei nuovi browser che supportano il differimento, ma non ti aiuterà affatto nei browser più vecchi e non è molto più veloce del mettere semplicemente gli script davanti ai </body>quali funziona in tutti i browser. Quindi, puoi vedere perché è meglio metterli subito prima </body>.

Async è più utile quando non ti interessa davvero quando si carica lo script e nient'altro che dipende dall'utente dipende dal caricamento dello script stesso. L'esempio più spesso citato per l'utilizzo di asincrono è uno script di analisi come Google Analytics che non si desidera attendere nulla e non è urgente eseguire presto e si regge da solo, quindi nient'altro dipende da esso.

Di solito la libreria jQuery non è un buon candidato per l'asincronizzazione perché altri script dipendono da essa e si desidera installare i gestori di eventi in modo che la pagina possa iniziare a rispondere agli eventi dell'utente e potrebbe essere necessario eseguire un codice di inizializzazione basato su jQuery per stabilire lo stato iniziale della pagina. Può essere usato in modo asincrono, ma altri script dovranno essere codificati per non essere eseguiti fino al caricamento di jQuery.


8
Defer dovrebbe eseguirli ancora in ordine, ma eseguirli prima di dom-contentloaded. Ciò non significa che metterlo in testa sarebbe più veloce, dal momento che può iniziare a scaricarli PRIMA che il body html venga analizzato?
Kevin,

9
Hai detto che inserire gli script heade impostarli su defernon sarà più veloce di metterli prima </body>, ma da quello che ho letto non è corretto. Pensaci: se inserisci gli script <head>, inizieranno immediatamente a scaricare, mentre se sono proprio prima di </body>allora tutti gli altri elementi verranno scaricati per primi.
Nate

12
@Nate: non caricherà il tuo documento più velocemente, questo è il mio punto. Hai ragione che potrebbe migliorare il caricamento dello script prima, ma potrebbe anche rallentare il caricamento del documento e dei suoi contenuti perché stai usando parte della tua larghezza di banda e stai usando una delle connessioni limitate che il browser farà a un determinato server carica lo script mentre tenta anche di caricare i tuoi contenuti.
jfriend00

4
"Se il tuo secondo script dipende dal primo script ... allora non puoi renderli né asincroni né differire" - non è vero, con il differimento vengono eseguiti in ordine.
DisgruntledGoat

2
A questo punto, il requisito </body> non è realmente necessario con gli sviluppi del browser dal 2012 quando questa risposta è stata pubblicata.
bgcode

845

Questa immagine spiega il normale tag di script, asincrono e differisci

inserisci qui la descrizione dell'immagine

  • Gli script asincroni vengono eseguiti non appena lo script viene caricato, quindi non garantisce l'ordine di esecuzione (uno script incluso alla fine potrebbe essere eseguito prima del primo file di script)

  • Rimanda gli script garantisce l'ordine di esecuzione in cui compaiono nella pagina.

Rif: link: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html


Penso che un esempio con più script sarebbe stato meglio per illustrare la loro sequenza
vsync il

4
@writofmandamus Sembra asyncche vincerà. Vedi stackoverflow.com/questions/13821151/…
Monsignor

Grazie per la buona spiegazione Tuttavia, le immagini non sono in scala. Nel caso del solo <script>tag, la lunghezza totale del caricamento della pagina è più lunga del tempo necessario per scaricare il file di script.
arni,

@BhavikHirani Secondo questo sito , l'utilizzo sia asincrono che differito nello stesso tag di script utilizza asincrono se il browser lo supporta o ricade per differire se non supporta asincrono, ma supporta il differimento. I comportamenti sono piuttosto diversi, quindi non consiglierei di usarli entrambi, poiché il risultato è imprevedibile e può essere un'ottima fonte di bug.
Adrian Wiik

@arni Solo se la larghezza di banda è completamente utilizzata, cosa che raramente lo è. Entrambi i download condividono la larghezza di banda, non ne bloccano una. - Inoltre: queste immagini mostrano l'analisi in verde, non il download.
Robert Siemer

213

HTML5: async,defer

In HTML5, puoi indicare al browser quando eseguire il tuo codice JavaScript. Vi sono 3 possibilità:

<script       src="myscript.js"></script>

<script async src="myscript.js"></script>

<script defer src="myscript.js"></script>
  1. Senza asynco defer, il browser eseguirà immediatamente lo script prima di eseguire il rendering degli elementi che si trovano sotto il tag dello script.

  2. Con async(asincrono), il browser continuerà a caricare la pagina HTML e a renderla mentre il browser carica ed esegue lo script contemporaneamente.

  3. Con defer, il browser eseguirà il tuo script al termine dell'analisi della pagina. (non è necessario terminare il download di tutti i file di immagine. Questo va bene.)


Modello di blogger.com richiesto async=""prima di poter convalidare e salvare le modifiche al modello.
noobninja,

1
Nota: non esiste alcuna garanzia che gli script vengano eseguiti nell'ordine in cui sono stati specificati utilizzando Async. "Quindi se il tuo secondo script dipende dal primo script, evita Async."
Faisal Naseer,

2
async- Gli script vengono eseguiti nel momento in cui sono stati scaricati, senza considerare il loro ordine nel file HTML.
vsync,

30

Entrambi asynce gli deferscript iniziano a scaricare immediatamente senza mettere in pausa il parser ed entrambi supportano un facoltativoonload gestore per rispondere alla necessità comune di eseguire l'inizializzazione che dipende dallo script.

La differenza tra asynce defercentrata attorno all'esecuzione dello script. Ogni asyncscript viene eseguito alla prima opportunità al termine del download e prima dell'evento di caricamento della finestra. Ciò significa che è possibile (e probabilmente) che gli asyncscript non vengano eseguiti nell'ordine in cui si trovano nella pagina. Considerando che gli deferscript, d'altra parte, sono garantiti per essere eseguiti nell'ordine in cui si verificano nella pagina. Tale esecuzione ha inizio al termine dell'analisi, ma prima DOMContentLoadeddell'evento del documento .

Fonte e ulteriori dettagli: qui .


25

Di fronte allo stesso tipo di problema e ora ho capito chiaramente come funzioneranno entrambi. Spero che questo link di riferimento sia utile ...

Async

Quando aggiungi l'attributo asincrono al tag dello script, si verificherà quanto segue.

<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
  1. Invia richieste parallele per recuperare i file.
  2. Continua ad analizzare il documento come se non fosse mai stato interrotto.
  3. Eseguire i singoli script nel momento in cui i file vengono scaricati.

Differire

Il differimento è molto simile all'asincrono con una grande differenza. Ecco cosa succede quando un browser incontra uno script con l'attributo differisci.

<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
  1. Invia richieste parallele per recuperare i singoli file.
  2. Continua ad analizzare il documento come se non fosse mai stato interrotto.
  3. Completare l'analisi del documento anche se i file di script sono stati scaricati.
  4. Eseguire ogni script nell'ordine in cui sono stati rilevati nel documento.

Riferimento: differenza tra Async e Defer


7

asynce deferscaricherà il file durante l'analisi HTML. Entrambi non interromperanno il parser.

  • Lo script con asyncattributo verrà eseguito una volta scaricato. Mentre lo script con deferattributo verrà eseguito dopo aver completato l'analisi DOM.

  • Gli script caricati con asyncnon garantiscono alcun ordine. Mentre gli script caricati con l' deferattributo mantengono l'ordine in cui compaiono sul DOM.

Utilizzare <script async>quando lo script non si basa su nulla. quando lo script dipende usare.

La soluzione migliore sarebbe aggiungere la parte inferiore del corpo. Non ci saranno problemi con il blocco o il rendering.


Voglio solo fare alcuni chiarimenti qui, due cose stanno accadendo qui 1. Download di risorse 2. Esecuzione di risorse. Il download della risorsa in entrambi i casi (asincrono e differito) non blocca, significa che non bloccano l'analisi di HTML, mentre l'esecuzione in asincrono blocca l'analisi e in caso di differimento, l'esecuzione ha luogo dopo l'analisi del markup HTML, quindi non bloccando in questo caso.
dal

5

Penso che Jake Archibald ci abbia presentato alcuni approfondimenti nel 2013 che potrebbero aggiungere ancora più positività all'argomento:

https://www.html5rocks.com/en/tutorials/speed/script-loading/

Il Santo Graal sta scaricando immediatamente una serie di script senza bloccare il rendering ed eseguirlo il prima possibile nell'ordine in cui sono stati aggiunti. Purtroppo HTML ti odia e non ti consente di farlo.

(...)

La risposta è in realtà nelle specifiche HTML5, sebbene sia nascosta nella parte inferiore della sezione di caricamento degli script. " L'attributo IDL asincrono controlla se l'elemento verrà eseguito in modo asincrono o meno. Se è impostato il flag" force-async "dell'elemento, quindi, al momento di ottenere, l'attributo IDL asincrono deve restituire true e, al momento dell'impostazione, il" force-async " la bandiera deve prima essere disinserita ... ".

(...)

Gli script creati dinamicamente e aggiunti al documento sono asincroni per impostazione predefinita , non bloccano il rendering e si eseguono non appena vengono scaricati, il che significa che potrebbero uscire nell'ordine sbagliato. Tuttavia, possiamo contrassegnarli esplicitamente come non asincroni:

[
    '//other-domain.com/1.js',
    '2.js'
].forEach(function(src) {
    var script = document.createElement('script');
    script.src = src;
    script.async = false;
    document.head.appendChild(script);
});

Questo dà ai nostri script un mix di comportamenti che non possono essere raggiunti con un semplice HTML. Essendo esplicitamente non asincroni, gli script vengono aggiunti a una coda di esecuzione, la stessa coda a cui vengono aggiunti nel nostro primo esempio in HTML semplice. Tuttavia, essendo creati dinamicamente, vengono eseguiti al di fuori dell'analisi del documento, quindi il rendering non viene bloccato durante il download (non confondere il caricamento di script non asincroni con la sincronizzazione XHR, che non è mai una buona cosa).

Lo script sopra dovrebbe essere incluso in linea nella parte superiore delle pagine, accodando i download degli script il prima possibile senza interrompere il rendering progressivo ed essere eseguito il prima possibile nell'ordine specificato. "2.js" può essere scaricato gratuitamente prima di "1.js", ma non verrà eseguito fino a quando "1.js" non sarà stato scaricato o eseguito correttamente o non verrà eseguito. Evviva! download asincrono ma esecuzione ordinata !

Tuttavia, questo potrebbe non essere il modo più veloce per caricare gli script:

(...) Con l'esempio sopra, il browser deve analizzare ed eseguire gli script per scoprire quali script scaricare. Ciò nasconde i tuoi script dagli scanner precaricati. I browser utilizzano questi scanner per scoprire le risorse sulle pagine che probabilmente visiterai in seguito, oppure per scoprire le risorse delle pagine mentre il parser è bloccato da un'altra risorsa.

Possiamo aggiungere nuovamente la rilevabilità inserendola nella parte superiore del documento:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

Questo dice al browser che la pagina ha bisogno di 1.js e 2.js. link [rel = subresource] è simile al link [rel = prefetch], ma con una semantica diversa. Purtroppo al momento è supportato solo in Chrome e devi dichiarare quali script caricare due volte, una volta tramite elementi di collegamento e di nuovo nel tuo script.

Correzione: inizialmente avevo dichiarato che erano stati raccolti dallo scanner di precarico, non lo sono, sono stati raccolti dal normale parser. Tuttavia, lo scanner di precaricamento potrebbe rilevarli, ma non lo fa ancora, mentre gli script inclusi nel codice eseguibile non possono mai essere precaricati. Grazie a Yoav Weiss che mi ha corretto nei commenti.


1

Sembra che il comportamento di differimento e asincrono dipenda dal browser, almeno dalla fase di esecuzione. NOTA, il differimento si applica solo agli script esterni. Suppongo che l'asincrono segua lo stesso schema.

In IE 11 e versioni precedenti, l'ordine sembra essere così:

  • asincrono (potrebbe eseguire parzialmente durante il caricamento della pagina)
  • nessuno (potrebbe essere eseguito durante il caricamento della pagina)
  • differire (viene eseguito dopo il caricamento della pagina, tutti differiscono in ordine di posizionamento nel file)

In Edge, Webkit, ecc., L'attributo asincrono sembra essere ignorato o posizionato alla fine:

  • data-pagepeed-no-defer (viene eseguita prima di qualsiasi altro script, mentre la pagina viene caricata)
  • nessuno (potrebbe essere eseguito durante il caricamento della pagina)
  • differire (attende fino al caricamento del DOM, tutti differiscono in ordine di posizionamento nel file)
  • asincrono (sembra attendere fino al caricamento di DOM)

Nei browser più recenti, l'attributo data-pagepeed-no-defer viene eseguito prima di qualsiasi altro script esterno. Questo è per gli script che non dipendono dal DOM.

NOTA: utilizzare il differimento quando è necessario un ordine esplicito di esecuzione degli script esterni. Questo dice al browser di eseguire tutti gli script differiti in ordine di posizionamento nel file.

A parte: le dimensioni dei javascript esterni erano importanti durante il caricamento ... ma non avevano alcun effetto sull'ordine di esecuzione.

Se sei preoccupato per le prestazioni dei tuoi script, potresti prendere in considerazione la minimizzazione o semplicemente caricarli dinamicamente con un XMLHttpRequest.


data-pagespeed-no-deferè un attributo utilizzato dal modulo PageSpeed lato server . L' attributo da solo non ha alcun effetto in nessun browser. data-pagespeed-no-defer
Qtax,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.