Come funziona esattamente <script defer = “defer”>?


208

Ho alcuni <script>elementi e il codice in alcuni di essi dipende dal codice in altri <script>elementi. Ho visto che l' deferattributo può tornare utile in quanto consente di posticipare i blocchi di codice durante l'esecuzione.

Per provarlo l'ho eseguito su Chrome: http://jsfiddle.net/xXZMN/ .

<script defer="defer">alert(2);</script>
<script>alert(1)</script>
<script defer="defer">alert(3);</script>

Tuttavia, avvisa 2 - 1 - 3. Perché non avvisa 1 - 2 - 3?


2
Forse dai un'occhiata a questo articolo . E, come sempre, IE ha una propria opinione su cosa significhi qualcosa e ha deciso di caricare prima lo script ma ritardare l'esecuzione fino a quando non viene caricato il corpo (in genere).
Brad Christie,

Grazie, tuttavia, la pagina di test ha un risultato diverso su Chrome: websiteoptimization.com/speed/tweak/defer/test . Lo screenshot mostra come me lo sarei aspettato, mentre Chrome sembra eseguire prima il differito.
pimvdb

1
Penso che troverai la definizione di differimento di IE, che corrisponda all'intento del W3C di differire nelle specifiche DOM di livello 1.
Mark At Ramp51

41
Come già sottolineato da Alohci nella sua risposta, secondo lo standard HTML defer è valido solo quando si specifica src. Questo potrebbe essere un motivo per cui il tuo esempio non ha funzionato come previsto nella maggior parte dei browser.
Pankrat,

2
@Pankrat Storia vera! Prova jsfiddle.net/xXZMN/50 Testato in
Firefox24

Risposte:


51

AGGIORNATO: 19/02/2016

Considera questa risposta obsoleta. Fare riferimento ad altre risposte su questo post per informazioni relative alla versione più recente del browser.


Fondamentalmente, il differimento dice al browser di attendere "fino a quando non è pronto" prima di eseguire il javascript in quel blocco di script. Di solito ciò avviene dopo che il DOM ha terminato il caricamento e document.readyState == 4

L'attributo defer è specifico di Internet Explorer. In Internet Explorer 8, su Windows 7 il risultato che vedo nella tua pagina di test JS Fiddle è, 1 - 2 - 3.

I risultati possono variare da browser a browser.

http://msdn.microsoft.com/en-us/library/ms533719(v=vs.85).aspx

Contrariamente alla credenza popolare, IE segue gli standard più spesso delle persone, in realtà l'attributo "differisci" è definito nella specifica DOM di livello 1 http://www.w3.org/TR/REC-DOM-Level-1/level -one-html.html

La definizione di differimento del W3C: http://www.w3.org/TR/REC-html40/interact/scripts.html#adef-defer :

"Se impostato, questo attributo booleano fornisce un suggerimento all'agente utente che lo script non genererà alcun contenuto del documento (ad esempio, nessun" document.write "in javascript) e quindi l'agente utente può continuare ad analizzare e renderizzare."


8
@ MarkAtRamp51 - Se la tua risposta è obsoleta, dovresti modificarla invece di lamentarti dei voti negativi nei commenti su altre risposte. I downgrade sono per le risposte "non utili".
Christian Conkle,

10
@ChristianConkle Apprezzo la lezione di etichetta, tuttavia le altre risposte qui sono aggiornate. Stavo affrontando il fatto che la risposta sbagliata non era stata selezionata al momento della domanda. Forse dovresti sorvegliare le persone che diffondono false valutazioni sulla comunità selezionando erroneamente le risposte, invece di cercare di ricordare alle persone che le cose cambiano nel tempo e il contesto è importante. Non vedo valore nel rimuovere la mia risposta poiché anche le informazioni storiche sono preziose.
Mark At Ramp51,

3
"Non vedo valore nel rimuovere la mia risposta poiché anche le informazioni storiche sono preziose" In quel caso, che ne dici di aggiungere una nota all'inizio sottolineando che si applica solo a pre-HTML5 e quindi collegando il "corretto" ( aggiornato) risposta? Ciò dovrebbe farti risparmiare un sacco di problemi (parlare come un ragazzo che ha anche accettato una risposta "sbagliata" una volta ed è stato "pressato dai pari" per cambiarla alla fine).
mgibsonbr,

3
@Leo non dovrebbe essere contrassegnato allora? Cercando "html5 defer script" questo è il terzo risultato in google. Questa risposta fornisce quindi a molti utenti una definizione obsoleta e errata. (La definizione corrente: "Indica che l'agente utente può differire l'elaborazione dello script. Vedere la definizione dell'attributo differire in HTML 4.0.").
Malavos,

2
@ MarkAtRamp51 Penso che dovresti aggiornare la tua risposta. Chiunque trovi questa domanda e quindi la tua risposta non riconoscerà le sue informazioni storiche. A loro sembrerà che sia la risposta che è corretta oggi. Ecco come funziona Internet. Quindi dovresti modificare la tua risposta, notare che una volta era corretta e fare riferimento alla risposta corretta.
Juuro,

167

Alcuni frammenti delle specifiche HTML5: http://w3c.github.io/html/semantics-scripting.html#element-attrdef-script-async

Gli attributi defer e async non devono essere specificati se l'attributo src non è presente.


Esistono tre modalità possibili che possono essere selezionate utilizzando questi attributi [asincrono e differisci]. Se l'attributo asincrono è presente, lo script verrà eseguito in modo asincrono, non appena sarà disponibile. Se l'attributo asincrono non è presente ma è presente l'attributo differito, lo script viene eseguito al termine dell'analisi della pagina. Se nessuno degli attributi è presente, lo script viene recuperato ed eseguito immediatamente, prima che l'agente utente continui ad analizzare la pagina.


I dettagli di elaborazione esatti per questi attributi sono, per ragioni prevalentemente storiche, un po 'non banali, che coinvolgono una serie di aspetti dell'HTML. I requisiti di implementazione sono quindi necessariamente sparsi in tutte le specifiche. Gli algoritmi di seguito (in questa sezione) descrivono il nucleo di questa elaborazione, ma questi algoritmi fanno riferimento e sono referenziati dalle regole di analisi per i tag di inizio e fine degli script in HTML, in contenuto estraneo e in XML, le regole per document.write () metodo, gestione degli script, ecc.


Se l'elemento ha un attributo src e l'elemento ha un attributo differito e l'elemento è stato contrassegnato come "inserito dal parser" e l'elemento non ha un attributo asincrono:

L'elemento deve essere aggiunto alla fine dell'elenco di script che verrà eseguito al termine dell'analisi del documento associato al documento del parser che ha creato l'elemento.


37
Forse, la mia risposta qui impedirà alle persone di votare la mia risposta, a causa del tuo commento non utile. La risposta accettata non è sbagliata, la risposta è diversa, perché all'inizio del 2011 le specifiche HTML5 erano meno rilevanti per i browser web tradizionali di quanto non sia attualmente. Questa risposta potrebbe essere migliore per il futuro, ma la risposta accettata non è ERRATA da nessuno standard.
Mark At Ramp51,

3
Sebbene sia utile sapere cosa dicono le specifiche, si scopre che alcuni browser come IE <9 implementano defermale . Se lo usi defer, non puoi fare affidamento sui file di script eseguiti in ordine in alcuni browser.
Flimm,


La prima citazione non è più valida, giusto? Ora posso leggere questo: "L'attributo non deve essere specificato se l'attributo src non è presente o se lo script non è uno script classico". E uno script classico è anche uno senza src = "".
Félix Sanz,

158

La vera risposta è: perché non puoi fidarti del differimento.

Nel concetto, differire e asincrono differiscono come segue:

async consente di scaricare lo script in background senza bloccarlo. Quindi, nel momento in cui termina il download, il rendering viene bloccato e lo script viene eseguito. Il rendering riprende quando lo script è stato eseguito.

differire fa la stessa cosa, ad eccezione delle affermazioni per garantire che gli script vengano eseguiti nell'ordine in cui sono stati specificati nella pagina e che verranno eseguiti al termine dell'analisi del documento. Pertanto, alcuni script potrebbero terminare il download, quindi sedersi e attendere gli script scaricati in seguito, ma visualizzati prima di essi.

Sfortunatamente, a causa di ciò che è veramente un combattimento tra gatti standard, la definizione del differimento varia da specifica a specifica, e anche nelle specifiche più recenti non offre una garanzia utile. Come le risposte qui e questo problema dimostrano, i browser implementano il differimento in modo diverso:

  • In alcune situazioni alcuni browser hanno un bug che causa l' deferesaurimento degli script.
  • Alcuni browser ritardano l' DOMContentLoadedevento fino al termine del defercaricamento degli script, altri no.
  • Alcuni browser obbediscono deferad <script>elementi con codice incorporato e senza srcattributo, e altri lo ignorano.

Fortunatamente la specifica specifica almeno che l'asincrono ha la precedenza sul differimento. Quindi puoi trattare tutti gli script come asincroni e ottenere un'ampia gamma di supporto del browser in questo modo:

<script defer async src="..."></script>

Il 98% dei browser in uso in tutto il mondo e il 99% negli Stati Uniti eviteranno di bloccare con questo approccio.

(Se devi attendere fino al termine dell'analisi del documento, ascolta l'evento DOMContentLoadeddell'evento o usa la comoda .ready()funzione di jQuery . Ti consigliamo di farlo comunque per tornare indietro con grazia sui browser che non si implementano deferaffatto.)


13
Grazie, la tua risposta è stata la più utile per me!
markus

5
Credo che questo non sia corretto. Il vantaggio del differimento è che non viene eseguito fino al completamento dell'analisi della pagina. Questa pagina ha una buona visuale per spiegare la differenza tra asincrono e differire: peter.sh/experiments/…
tinkerr

1
@tinkerr In concept hai ragione; in pratica questo non risulta essere vero. Poiché non è implementato in modo coerente, la garanzia della sequenza non è universale e quindi non è una garanzia. Quando si implementa qualcosa che ti interessa dell'esecuzione. L'intento del design è carino, ma non particolarmente utile.
Chris Moschini,

Volevo solo sottolineare che Opera ha supportato l' deferattributo dalla versione 15 , che è stata rilasciata il 2 giugno 2013 .

1
@VikasBansal Per i browser meno recenti che non supportano l'asincronizzazione, ovvero IE precedente.
Chris Moschini,

13

deferpuò essere utilizzato solo nel <script>tag per l' inclusione di script esterni . Pertanto si consiglia di utilizzare i <script>tag nella <head>sezione.


8

Poiché l'attributo defer funziona solo con tag script con src. Trovato un modo per imitare il differimento per gli script incorporati. Usa l'evento DOMContentLoaded.

<script defer src="external-script.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
    // Your inline scripts which uses methods from external-scripts.
});
</script>

Questo perché, l'evento DOMContentLoaded viene generato dopo che gli script posticipati differiti sono stati caricati completamente.


6

L'attributo defer è solo per script esterni (dovrebbe essere usato solo se è presente l'attributo src).



4

Dai un'occhiata a questo eccellente articolo Immergiti nelle oscure acque del caricamento degli script dello sviluppatore Google Jake Archibald scritto nel 2013.

Citando la sezione pertinente da quell'articolo:

Differire

<script src="//other-domain.com/1.js" defer></script>
<script src="2.js" defer></script>

La specifica dice : Scarica insieme, esegui nell'ordine appena prima di DOMContentLoaded. Ignora "differisci" sugli script senza "src".

IE <10 dice : Potrei eseguire 2.js a metà dell'esecuzione di 1.js. Non è divertente ??

I browser in rosso dicono : Non ho idea di cosa sia questa "differita", caricherò gli script come se non ci fossero.

Altri browser dicono : Ok, ma potrei non ignorare "differire" sugli script senza "src".

(Aggiungerò che le prime versioni di Firefox attivano DOMContentLoaded prima che gli deferscript finiscano di funzionare, secondo questo commento .)

I browser moderni sembrano supportare asynccorrettamente, ma devi essere OK con gli script che non funzionano e probabilmente prima di DOMContentLoaded.


1

Questo attributo booleano è impostato per indicare a un browser che lo script deve essere eseguito dopo che il documento è stato analizzato. Dal momento che questa funzione non è stata ancora implementata da tutti gli altri principali browser, gli autori non dovrebbero presumere che l'esecuzione dello script verrà effettivamente rinviata. Non chiamare mai document.write () da uno script di differimento (dal momento che Gecko 1.9.2, questo farà saltare il documento). L'attributo defer non dovrebbe essere usato su script che non hanno l'attributo src. Da Gecko 1.9.2, l'attributo defer viene ignorato negli script che non hanno l'attributo src. Tuttavia, in Gecko 1.9.1 anche gli script incorporati vengono rinviati se l'attributo differito è impostato.

differire funziona con chrome, firefox, ovvero> 7 e Safari

rif: https://developer.mozilla.org/en-US/docs/HTML/Element/script


0

L'attributo defer è un attributo booleano.

Se presente, specifica che lo script viene eseguito al termine dell'analisi della pagina.

Nota: l'attributo defer è solo per script esterni (dovrebbe essere usato solo se è presente l'attributo src).

Nota: esistono diversi modi per eseguire uno script esterno:

Se async è presente: lo script viene eseguito in modo asincrono con il resto della pagina (lo script verrà eseguito mentre la pagina continua l'analisi) Se async non è presente e il differimento è presente: lo script viene eseguito al termine dell'analisi della pagina Se non è presente né asincrono né differisci: lo script viene recuperato ed eseguito immediatamente, prima che il browser continui ad analizzare la pagina

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.