I CSS dovrebbero sempre precedere Javascript?


897

In innumerevoli posti online ho visto la raccomandazione di includere CSS prima di JavaScript. Il ragionamento è generalmente, di questa forma :

Quando si tratta di ordinare CSS e JavaScript, si desidera che il CSS venga prima di tutto. Il motivo è che il thread di rendering ha tutte le informazioni di stile necessarie per eseguire il rendering della pagina. Se JavaScript include prima di tutto, il motore JavaScript deve analizzare tutto prima di continuare con il prossimo set di risorse. Ciò significa che il thread di rendering non può mostrare completamente la pagina, poiché non ha tutti gli stili di cui ha bisogno.

I miei test effettivi rivelano qualcosa di completamente diverso:

Il mio cablaggio di prova

Uso il seguente script Ruby per generare ritardi specifici per varie risorse:

require 'rubygems'
require 'eventmachine'
require 'evma_httpserver'
require 'date'

class Handler  < EventMachine::Connection
  include EventMachine::HttpServer

  def process_http_request
    resp = EventMachine::DelegatedHttpResponse.new( self )

    return unless @http_query_string

    path = @http_path_info
    array = @http_query_string.split("&").map{|s| s.split("=")}.flatten
    parsed = Hash[*array]

    delay = parsed["delay"].to_i / 1000.0
    jsdelay = parsed["jsdelay"].to_i

    delay = 5 if (delay > 5)
    jsdelay = 5000 if (jsdelay > 5000)

    delay = 0 if (delay < 0) 
    jsdelay = 0 if (jsdelay < 0)

    # Block which fulfills the request
    operation = proc do
      sleep delay 

      if path.match(/.js$/)
        resp.status = 200
        resp.headers["Content-Type"] = "text/javascript"
        resp.content = "(function(){
            var start = new Date();
            while(new Date() - start < #{jsdelay}){}
          })();"
      end
      if path.match(/.css$/)
        resp.status = 200
        resp.headers["Content-Type"] = "text/css"
        resp.content = "body {font-size: 50px;}"
      end
    end

    # Callback block to execute once the request is fulfilled
    callback = proc do |res|
        resp.send_response
    end

    # Let the thread pool (20 Ruby threads) handle request
    EM.defer(operation, callback)
  end
end

EventMachine::run {
  EventMachine::start_server("0.0.0.0", 8081, Handler)
  puts "Listening..."
}

Il mini server sopra riportato mi consente di impostare ritardi arbitrari per i file JavaScript (sia server che client) e ritardi CSS arbitrari. Ad esempio, http://10.0.0.50:8081/test.css?delay=500mi dà un ritardo di 500 ms nel trasferimento del CSS.

Uso la pagina seguente per testare.

<!DOCTYPE html>
<html>
  <head>
      <title>test</title>
      <script type='text/javascript'>
          var startTime = new Date();
      </script>
      <link href="http://10.0.0.50:8081/test.css?delay=500" type="text/css" rel="stylesheet">
      <script type="text/javascript" src="http://10.0.0.50:8081/test2.js?delay=400&amp;jsdelay=1000"></script> 
  </head>
  <body>
    <p>
      Elapsed time is: 
      <script type='text/javascript'>
        document.write(new Date() - startTime);
      </script>
    </p>    
  </body>
</html>

Quando includo prima il CSS, il rendering della pagina richiede 1,5 secondi:

Prima i CSS

Quando includo prima JavaScript, la pagina impiega 1,4 secondi per il rendering:

JavaScript prima

Ottengo risultati simili in Chrome, Firefox e Internet Explorer. In Opera, tuttavia, l'ordinamento semplicemente non ha importanza.

Ciò che sembra accadere è che l'interprete JavaScript si rifiuta di iniziare fino a quando non viene scaricato tutto il CSS. Quindi, sembra che avere JavaScript includa prima sia più efficiente poiché il thread JavaScript ottiene più tempo di esecuzione.

Mi sto perdendo qualcosa, la raccomandazione di inserire CSS include prima di JavaScript non è corretta?

È chiaro che potremmo aggiungere asincroni o utilizzare setTimeout per liberare il thread di rendering o inserire il codice JavaScript nel piè di pagina o utilizzare un caricatore JavaScript. Il punto qui è sull'ordinamento di bit JavaScript essenziali e bit CSS nella testa.


120
1511 vs 1422 è una differenza statisticamente significativa? Questo è il 6 percento. La soglia generale per la differenza di prestazione tra uomo notevole e medio è di circa il 20 percento.
Jeff Atwood,

15
il punto è che il riordino elimina questo ritardo arbitrario, puoi impostare il ritardo su qualsiasi cosa tu voglia, è solo una demo del problema.
Sam Saffron,

3
è stato il tuo ritardo di 100ms? la differenza nei tuoi screenshot è 89ms. Nel tuo URL lo è delay=400&amp;jsdelay=1000e delay=500non è vicino a 100ms o 89ms. Immagino di non essere chiaro a quali numeri ti riferisci.
Jeff Atwood,

4
"Se il Javascript include prima di tutto, il motore Javascript deve analizzare tutto prima di continuare con il prossimo set di risorse. Ciò significa che il thread di rendering non può mostrare completamente la pagina, dal momento che non ha tutti gli stili di cui ha bisogno ". - se l'inclusione JS è nella testa, allora la JS verrà eseguita prima del rendering della pagina, indipendentemente dal fatto che l'inclusione CSS fosse precedente o successiva.
nnnnnn,

162
Non sono sicuro se lo hai considerato, ma anche la percezione del tempo di caricamento è importante. Quindi, ad esempio, se il caricamento del CSS prima ti dà anche solo il colore / la trama dello sfondo della pagina, sembrerebbe essere più veloce. I tempi di caricamento assoluti potrebbero non essere indicativi di questo.
Rakesh Pai,

Risposte:


712

Questa è una domanda molto interessante Ho sempre messo i miei CSS <link href="...">prima dei miei JS <script src="...">perché "Ho letto una volta che è meglio". Quindi hai ragione; è giunto il momento di fare delle ricerche reali!

Ho impostato il mio cablaggio di prova in Nodo (codice sotto). Fondamentalmente, io:

  • Assicurati che non esistesse la memorizzazione nella cache HTTP, quindi il browser dovrebbe effettuare un download completo ogni volta che viene caricata una pagina.
  • Per simulare la realtà, ho incluso jQuery e il CSS H5BP (quindi c'è una discreta quantità di script / CSS da analizzare)
  • Imposta due pagine: una con CSS prima dello script, una con CSS dopo lo script.
  • Registrato il tempo impiegato per lo script esterno nella <head>da eseguire
  • Ha registrato il tempo impiegato per l' <body>esecuzione dello script inline per l' esecuzione, il che è analogo a DOMReady.
  • Invio ritardato di CSS e / o script al browser di 500 ms.
  • Ho eseguito il test 20 volte nei 3 principali browser.

risultati

Innanzitutto, con il file CSS ritardato di 500 ms:

     Browser: Chrome 18    | IE 9         | Firefox 9
         CSS: first  last  | first  last  | first last
=======================================================
Header Exec |              |              |
Average     | 583ms  36ms  | 559ms  42ms  | 565ms 49ms
St Dev      | 15ms   12ms  | 9ms    7ms   | 13ms  6ms
------------|--------------|--------------|------------
Body Exec   |              |              |
Average     | 584ms  521ms | 559ms  513ms | 565ms 519ms
St Dev      | 15ms   9ms   | 9ms    5ms   | 13ms  7ms

Successivamente, ho impostato jQuery per ritardare di 500ms invece del CSS:

     Browser: Chrome 18    | IE 9         | Firefox 9
         CSS: first  last  | first  last  | first last
=======================================================
Header Exec |              |              |
Average     | 597ms  556ms | 562ms  559ms | 564ms 564ms
St Dev      | 14ms   12ms  | 11ms   7ms   | 8ms   8ms
------------|--------------|--------------|------------
Body Exec   |              |              |
Average     | 598ms  557ms | 563ms  560ms | 564ms 565ms
St Dev      | 14ms   12ms  | 10ms   7ms   | 8ms   8ms

Infine, ho impostato sia jQuery che CSS per ritardare di 500ms:

     Browser: Chrome 18    | IE 9         | Firefox 9
         CSS: first  last  | first  last  | first last
=======================================================
Header Exec |              |              |
Average     | 620ms  560ms | 577ms  577ms | 571ms 567ms
St Dev      | 16ms   11ms  | 19ms   9ms   | 9ms   10ms
------------|--------------|--------------|------------
Body Exec   |              |              |
Average     | 623ms  561ms | 578ms  580ms | 571ms 568ms
St Dev      | 18ms   11ms  | 19ms   9ms   | 9ms   10ms

conclusioni

Innanzitutto, è importante notare che sto operando partendo dal presupposto che tu abbia degli script situati nel <head>tuo documento (al contrario della fine del <body>). Esistono vari argomenti sul perché potresti collegare i tuoi script nella parte <head>opposta alla fine del documento, ma questo è al di fuori dell'ambito di questa risposta. Si tratta strettamente di se <script>s dovrebbe andare prima di <link>s in <head>.

Nei moderni browser DESKTOP, sembra che il collegamento ai CSS non fornisca mai un miglioramento delle prestazioni. Mettere CSS dopo lo script ti dà una banale quantità di guadagno quando sia il CSS che lo script sono in ritardo, ma ti dà grandi guadagni quando il CSS è in ritardo. (Mostrato dalle lastcolonne nella prima serie di risultati.)

Dato che il collegamento a CSS per ultimo non sembra compromettere le prestazioni ma può fornire vantaggi in determinate circostanze, è necessario collegarsi a fogli di stile esterni dopo aver collegato a script esterni solo su browser desktop se le prestazioni dei browser precedenti non sono un problema. Continua a leggere per la situazione mobile.

Perché?

Storicamente, quando un browser rilevava un <script>tag che puntava a una risorsa esterna, il browser smetteva di analizzare l'HTML, recuperare lo script, eseguirlo, quindi continuare ad analizzare l'HTML. Al contrario, se il browser rilevasse un <link>per un foglio di stile esterno, continuerebbe ad analizzare l'HTML mentre recupera il file CSS (in parallelo).

Quindi, il consiglio ampiamente ripetuto di mettere al primo posto i fogli di stile: avrebbero scaricato prima, e il primo script da scaricare poteva essere caricato in parallelo.

Tuttavia, i browser moderni (inclusi tutti i browser con cui ho provato sopra) hanno implementato l' analisi speculativa , in cui il browser "guarda avanti" nell'HTML e inizia a scaricare risorse prima che gli script vengano scaricati ed eseguiti.

Nei vecchi browser senza analisi speculativa, mettere gli script al primo posto influirà sulle prestazioni poiché non verranno scaricati in parallelo.

Supporto per il browser

L'analisi speculativa è stata implementata per la prima volta in: (insieme alla percentuale di utenti di browser desktop in tutto il mondo che utilizzano questa versione o superiore a gennaio 2012)

  • Chrome 1 (WebKit 525) (100%)
  • IE 8 (75%)
  • Firefox 3.5 (96%)
  • Safari 4 (99%)
  • Opera 11.60 (85%)

In totale, circa l'85% dei browser desktop attualmente in uso supporta il caricamento speculativo. Mettere script prima dei CSS avrà una penalità per le prestazioni del 15% degli utenti a livello globale ; YMMV in base al pubblico specifico del tuo sito. (E ricorda che quel numero si sta riducendo.)

Sui browser mobili, è un po 'più difficile ottenere numeri definitivi semplicemente a causa della diversità del browser mobile e del panorama del sistema operativo. Poiché il rendering speculativo è stato implementato in WebKit 525 (rilasciato nel marzo 2008) e quasi tutti i browser mobili utili si basano su WebKit, possiamo concludere che la maggior parte dei browser mobili dovrebbe supportarlo. Secondo quirksmode , iOS 2.2 / Android 1.0 utilizzano WebKit 525. Non ho idea di come sia Windows Phone.

Tuttavia, ho eseguito il test sul mio dispositivo Android 4 e mentre vedevo numeri simili ai risultati del desktop, l'ho collegato al fantastico nuovo debugger remoto in Chrome per Android e la scheda Rete ha mostrato che il browser era in attesa di download il CSS fino a quando gli script Java non sono stati caricati completamente - in altre parole, anche la versione più recente di WebKit per Android non sembra supportare l'analisi speculativa. Ho il sospetto che potrebbe essere disattivato a causa della CPU, memoria e / o vincoli di rete inerenti ai dispositivi mobili.

Codice

Perdona la sciattezza: questo era il Q&D.

app.js

var express = require('express')
, app = express.createServer()
, fs = require('fs');

app.listen(90);

var file={};
fs.readdirSync('.').forEach(function(f) {
    console.log(f)
    file[f] = fs.readFileSync(f);
    if (f != 'jquery.js' && f != 'style.css') app.get('/' + f, function(req,res) {
        res.contentType(f);
        res.send(file[f]);
    });
});


app.get('/jquery.js', function(req,res) {
    setTimeout(function() {
        res.contentType('text/javascript');
        res.send(file['jquery.js']);
    }, 500);
});

app.get('/style.css', function(req,res) {
    setTimeout(function() {
        res.contentType('text/css');
        res.send(file['style.css']);
    }, 500);
});


var headresults={
    css: [],
    js: []
}, bodyresults={
    css: [],
    js: []
}
app.post('/result/:type/:time/:exec', function(req,res) {
    headresults[req.params.type].push(parseInt(req.params.time, 10));
    bodyresults[req.params.type].push(parseInt(req.params.exec, 10));
    res.end();
});

app.get('/result/:type', function(req,res) {
    var o = '';
    headresults[req.params.type].forEach(function(i) {
        o+='\n' + i;
    });
    o+='\n';
    bodyresults[req.params.type].forEach(function(i) {
        o+='\n' + i;
    });
    res.send(o);
});

css.html

<!DOCTYPE html>
<html>
    <head>
        <title>CSS first</title>
        <script>var start = Date.now();</script>
        <link rel="stylesheet" href="style.css">
        <script src="jquery.js"></script>
        <script src="test.js"></script>
    </head>
    <body>
        <script>document.write(jsload - start);bodyexec=Date.now()</script>
    </body>
</html>

js.html

<!DOCTYPE html>
<html>
    <head>
        <title>CSS first</title>
        <script>var start = Date.now();</script>
        <script src="jquery.js"></script>
        <script src="test.js"></script>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <script>document.write(jsload - start);bodyexec=Date.now()</script>
    </body>
</html>

test.js

var jsload = Date.now();


$(function() {
    $.post('/result' + location.pathname.replace('.html','') + '/' + (jsload - start) + '/' + (bodyexec - start));
});

jquery.js era jquery-1.7.1.min.js


137
questa è una risposta fantastica, grazie per aver usato la scienza! Per il tuo risultato "nei browser moderni, sembra che il collegamento al CSS non fornisca mai un miglioramento delle prestazioni" , penso che la risposta al titolo della domanda sia , il vecchio consiglio del CSS prima non è chiaramente valido.
Jeff Atwood,

Per quanto riguarda l'aggiornamento di @ josh3736 sull'inverso sul cellulare ... questo è un caso per non saltare la pistola su questo cambiamento significativo. Sarei curioso di sapere come si comportano gli altri browser per dispositivi mobili (webkit, geco, presto, tridente, ecc.) Poiché le prestazioni nei dispositivi mobili sono spesso più importanti.
scunliffe,

1
Dovresti anche provare ad aggiungere un po 'di lentezza alla stampa di css / js, per simulare le velocità di un server lento.
Kirb,

1
"In primo luogo, è importante notare che sto operando partendo dal presupposto che tu abbia degli script situati nel <head>tuo documento (al contrario della fine del <body>)." Vorrei evidenziarlo molto prima nella risposta, come nella parte superiore. Includere un scriptin headche si riferisce a un file esterno non è quasi mai corretto, da quasi tutte le prospettive (certamente non uno di prestazioni). Non ricordo di aver mai dovuto farlo nella vita reale. La strana o due righe dello script inline forse, ma questo è tutto. Il valore predefinito, senza molto buone ragioni contrarie, dovrebbe essere la fine del corpo.
TJ Crowder,

1
Sotto votato, jQuery non è JavaScript e gonfia ulteriormente la pagina, pertanto i risultati non sono obiettivi.
Giovanni,

303

Ci sono due ragioni principali per mettere CSS prima di JavaScript.

  1. I vecchi browser (Internet Explorer 6-7, Firefox 2, ecc.) Bloccavano tutti i download successivi quando iniziavano a scaricare uno script. Quindi, se hai a.jsseguito b.css, vengono scaricati in sequenza: prima a poi b. Se lo hai b.cssseguito a.js, vengono scaricati in parallelo in modo che la pagina si carichi più rapidamente.

  2. Non viene visualizzato nulla fino a quando non vengono scaricati tutti i fogli di stile, questo è vero in tutti i browser. Gli script sono diversi: bloccano il rendering di tutti gli elementi DOM che si trovano sotto il tag di script nella pagina. Se metti i tuoi script in HEAD, significa che l'intera pagina viene bloccata dal rendering fino a quando non vengono scaricati tutti i fogli di stile e tutti gli script. Mentre ha senso bloccare tutto il rendering per i fogli di stile (in modo da ottenere lo stile corretto la prima volta ed evitare il flash di FOUC di contenuto non elaborato), non ha senso bloccare il rendering dell'intera pagina per gli script. Spesso gli script non influenzano alcun elemento DOM o solo una parte degli elementi DOM. È meglio caricare gli script il più in basso possibile nella pagina o anche caricarli in modo asincrono.

È divertente creare esempi con Cuzillion . Ad esempio, questa pagina ha uno script in HEAD, quindi l'intera pagina è vuota fino al termine del download. Tuttavia, se spostiamo lo script alla fine del blocco BODY, l'intestazione della pagina viene visualizzata poiché quegli elementi DOM si trovano sopra il tag SCRIPT, come puoi vedere in questa pagina .


10
L'onorevole Steve mi ha battuto alla risposta, ma aggiungerò un articolo pertinente a ciò che menziona: stevesouders.com/blog/2009/04/27/…
Juan Pablo Buritica,

4
vedi quali browser supportano l' asyncattributo, che Steve consiglia qui quando dice "caricali ancora meglio in modo asincrono" - stackoverflow.com/questions/1834077/…
Jeff Atwood

Ehi, puoi dirmi perché qualcuno dovrebbe collegare i file CSS con le @importdirettive?
Josh Stodola,

6
Qual è la fonte per 2), e se è vero, puoi spiegare perché a volte una pagina finisce di caricare il contenuto, quindi il CSS viene applicato un secondo o due dopo? (Questo è successo, raramente, sulle mie pagine in cui il CSS era nei tag <head>)
Izkata

2
Quindi dovremmo mettere jQuery+ jQuery UI+ $(document).ready(function () { });alla fine della pagina? Funzionerà sempre come previsto?
Olivier Pons,

42

Non vorrei enfatizzare troppo i risultati che hai ottenuto, credo che sia soggettivo, ma ho un motivo per spiegarti che è meglio inserire nel CSS prima di js.

Durante il caricamento del tuo sito Web, ci sono due scenari che potresti vedere:

CASO 1: schermo bianco> sito Web non stilato> sito Web in stile> interazione> sito Web in stile e interattivo

CASO 2: schermo bianco> sito Web non in stile> interazione> sito Web in stile> sito Web in stile e interattivo


Non posso onestamente immaginare che nessuno scelga il Caso 2. Ciò significherebbe che i visitatori che utilizzano connessioni Internet lente si troveranno di fronte a un sito Web non stilato, che consente loro di interagire con esso utilizzando Javascript (poiché è già caricato). Inoltre, la quantità di tempo trascorso a guardare un sito Web non modificato verrebbe massimizzata in questo modo. Perché qualcuno lo vorrebbe?

Funziona anche meglio come afferma jQuery

"Quando si utilizzano script che si basano sul valore delle proprietà di stile CSS, è importante fare riferimento a fogli di stile esterni o incorporare elementi di stile prima di fare riferimento agli script".

Quando i file vengono caricati nell'ordine sbagliato (prima JS, quindi CSS), qualsiasi codice Javascript basato su proprietà impostate nei file CSS (ad esempio la larghezza o l'altezza di un div) non verrà caricato correttamente. Sembra che con un ordine di caricamento errato, le proprietà corrette siano "a volte" note a Javascript (forse questo è causato da una condizione di competizione?). Questo effetto sembra maggiore o minore a seconda del browser utilizzato.


2
Come faresti a garantire che tutti i CSS siano stati caricati prima che javascript venga eseguito? Puoi? o se il tuo javascript dovrebbe essere abbastanza robusto da gestire la situazione in cui gli stili potrebbero non essere necessariamente caricati.
Jonnio,

@Jonnio Se il tuo JS ha una dipendenza, allora dovresti renderla esplicita. Altrimenti, avrai sempre rari problemi di temporizzazione. I moduli ES6 sono un buon modo per farlo, ma ci sono anche molte librerie che potrebbero essere utilizzate.
kmkemp

26

I test sono stati eseguiti sul personal computer o su un server Web? È una pagina vuota o è un sistema online complesso con immagini, database, ecc.? I tuoi script eseguono una semplice azione evento hover o sono un componente fondamentale del modo in cui il tuo sito Web viene visualizzato e interagisce con l'utente? Ci sono molte cose da considerare qui e la rilevanza di queste raccomandazioni diventa quasi sempre una regola quando ti avventuri in uno sviluppo web di alto livello.

Lo scopo della regola "metti i fogli di stile in alto e gli script in basso" è che, in generale, è il modo migliore per ottenere un rendering progressivo ottimale , che è fondamentale per l'esperienza dell'utente.

A parte tutto: supponendo che il test sia valido e che tu stia davvero producendo risultati contrari alle regole popolari, non sarebbe una sorpresa, davvero. Ogni sito Web (e tutto ciò che serve per far apparire tutto sullo schermo di un utente) è diverso e Internet è in continua evoluzione.


1
Apprezzo il punto che stai mettendo in grassetto, ma l'OP sta parlando di cosa succede quando si cambia l'ordine con entrambi in alto, né in basso.
nnnnnn,

1
Pertanto, "supponendo che [il suo] test sia valido."
skippr

21

Includo i file CSS prima di Javascript per un motivo diverso.

Se il mio Javascript deve eseguire il ridimensionamento dinamico di alcuni elementi della pagina (per quei casi angolari in cui il CSS è davvero uno dei principali nella parte posteriore), il caricamento del CSS dopo che il JS è inesorabile può portare a condizioni di gara, in cui l'elemento viene ridimensionato prima degli stili CSS vengono applicati e quindi sembrano strani quando gli stili finalmente entrano in gioco. Se carico in anticipo il CSS, posso garantire che le cose funzionino nell'ordine previsto e che il layout finale sia quello che voglio che sia.


2
questo si interromperà un giorno su alcuni browser. Non sto indovinando.
jcolebrand,

1
jcolebrand: Sì, penso di non aver bevuto abbastanza caffè quando ho scritto questo. (A posteriori, immagino che le cose importanti siano solo per evitare il caricamento dinamico di CSS e mettere il JS all'interno di un evento domReady se è necessario eseguire il dimensionamento dinamico)
hugomg,

Gli script non dovrebbero cambiare alcun display. Questo è il lavoro CSS. HTML = contenuto, CSS = Come visualizzare il contenuto, javascript modifica il contenuto in modo dinamico. Inoltre js dovrebbe agire solo dopo (o mentre) il DOMContentLoaded viene attivato con alcune situazioni piccole ma molto specifiche.
brunoais,

@brunoais: alcuni layout possono essere creati solo con Javascript. Ad esempio, tutto ciò che deve essere ridimensionato dinamicamente deve essere realizzato tramite Javascript e alcune cose (come avere una dimensione del 100% - 20px) richiedono che Javascript sia fatto in modo portabile nei vecchi browser.
hugomg,

@missingno In questi casi, basta usare l'evento DOMContentLoaded, comunque. Ma capisco cosa intendi. (Stupido IE!)
brunoais il

10

La raccomandazione di includere CSS prima di JavaScript non è valida?

Non se lo tratti semplicemente come una raccomandazione. Ma se lo tratti come una regola dura e veloce? Sì, non è valido.

Da https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded

Il foglio di stile carica l'esecuzione dello script a blocchi, quindi se hai un <script> after a <link rel="stylesheet" ...>la pagina non finirà di analizzare - e DOMContentLoaded non si attiverà - fino a quando il foglio di stile non verrà caricato.

Sembra che tu abbia bisogno di sapere su cosa si basa ogni script e assicurarti che l'esecuzione dello script sia ritardata fino a dopo il giusto evento di completamento. Se lo script si basa solo sul DOM, può riprendere in ondomready / domcontentloaded, se si basa su immagini da caricare o fogli di stile da applicare, quindi se leggo correttamente il riferimento sopra, quel codice deve essere rinviato all'evento onload.

Non penso che una misura di calzino si adatti a tutti, anche se è così che vengono venduti e so che una taglia di scarpa non si adatta a tutti. Non penso che ci sia una risposta definitiva a cui caricare prima, stili o sceneggiatura. È più una decisione caso per caso di cosa deve essere caricato in quale ordine e cosa può essere rinviato a più tardi perché non si trova sul "percorso critico".

Per parlare con l'osservatore che ha commentato che è meglio ritardare la capacità degli utenti di interagire fino a quando il foglio è carino. Ci sono molti di voi là fuori e infastidite le vostre controparti che sentono il contrario. Sono venuti in un sito per raggiungere uno scopo e ritardare la loro capacità di interagire con un sito in attesa di cose che non contano per finire il caricamento sono molto frustranti. Non sto dicendo che ti sbagli, solo che dovresti essere consapevole che esiste un'altra fazione che non condivide la tua priorità.

Questa domanda si applica in particolare a tutti gli annunci pubblicati su siti Web. Mi piacerebbe se gli autori del sito rendessero solo i div del segnaposto per il contenuto dell'annuncio e si assicurassero che il loro sito fosse caricato e interattivo prima di iniettare gli annunci in un evento di caricamento. Anche allora vorrei vedere gli annunci caricati in serie invece che tutti in una volta perché hanno un impatto sulla mia capacità di scorrere il contenuto del sito mentre gli annunci gonfiati vengono caricati. Ma questo è solo un punto di vista delle persone.

  • Conosci i tuoi utenti e ciò che apprezzano.
  • Conosci i tuoi utenti e quale ambiente di navigazione usano.
  • Scopri cosa fa ogni file e quali sono i suoi prerequisiti. Far funzionare tutto avrà la precedenza sia sulla velocità che sulla bellezza.
  • Utilizzare strumenti che mostrano la linea temporale della rete durante lo sviluppo.
  • Test in ciascuno degli ambienti utilizzati dagli utenti. Potrebbe essere necessario modificare dinamicamente (lato server, durante la creazione della pagina) l'ordine di caricamento in base all'ambiente dell'utente.
  • In caso di dubbio, modificare l'ordine e misurare di nuovo.
  • È possibile che la miscelazione di stili e script nell'ordine di caricamento sia ottimale; non tutto l'uno quindi tutto l'altro.
  • Sperimenta non solo quale ordine caricare i file ma dove. Testa? Nel corpo? Dopo il corpo? DOM pronto / caricato? Caricato?
  • Prendi in considerazione le opzioni di asincronizzazione e differimento, se del caso, per ridurre il ritardo netto che l'utente sperimenterà prima di poter interagire con la pagina. Prova per determinare se aiutano o fanno male.
  • Ci saranno sempre dei compromessi da considerare nella valutazione dell'ordine di carico ottimale. Pretty vs. Responsive è solo uno.

1
L'articolo collegato non afferma più "Il foglio di stile carica l'esecuzione di script di blocco". Non è più vero?
Greg,

@Greg - È ancora vero. Gli script devono essere in grado di eseguire query sugli attributi DOM .style, quindi i fogli di stile bloccano comunque l'esecuzione degli script. Essi potrebbero non blocco di script di carico , se sono intelligenti, ma saranno bloccare eventi script.onLoad.
Jimmy Breck-McKye il

10

Aggiornato il 16-12-2017

Non ero sicuro dei test in OP. Ho deciso di sperimentare un po 'e ho finito per sballare alcuni dei miti.

Sincrono <script src...>bloccherà il download delle risorse sottostanti fino a quando non viene scaricato ed eseguito

Questo non è più vero . Dai un'occhiata alla cascata generata da Chrome 63:

<head>
<script src="//alias-0.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=1"></script>
<script src="//alias-1.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=2"></script>
<script src="//alias-2.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=3"></script>
</head>

Ispettore della rete di Chrome -> cascata

<link rel=stylesheet> non bloccherà il download e l'esecuzione degli script sottostanti

Questo non è corretto . Il foglio di stile non bloccherà il download, ma che sarà bloccare l'esecuzione dello script ( piccola spiegazione qui ). Dai un'occhiata al grafico delle prestazioni generato da Chrome 63:

<link href="//alias-0.redacted.com/payload.php?type=css&amp;delay=666" rel="stylesheet">
<script src="//alias-1.redacted.com/payload.php?type=js&amp;delay=333&amp;block=1000"></script>

Strumenti di sviluppo di Chrome -> prestazioni


Tenendo presente quanto sopra, i risultati in OP possono essere spiegati come segue:

CSS First:

CSS Download  500ms:<------------------------------------------------>
JS Download   400ms:<-------------------------------------->
JS Execution 1000ms:                                                  <-------------------------------------------------------------------------------------------------->
DOM Ready   @1500ms:                                                                                                                                                      

JS Primo:

JS Download   400ms:<-------------------------------------->
CSS Download  500ms:<------------------------------------------------>
JS Execution 1000ms:                                        <-------------------------------------------------------------------------------------------------->
DOM Ready   @1400ms:                                                                                                                                            

Questo è anche il motivo per cui document.write () è una delle peggiori idee mai realizzate per HTMLDOM.
brunoais,

1
The reason is that the script may want to get coordinates and other style-dependent properties of elements, like in the example above. Naturally, it has to wait for styles to load. javascript.info/… Perché la stessa ipotesi non si applica per la prima volta a JS? Non ha molto senso per me, l'ordine di esecuzione di JS non dice nulla sul suo scopo.
Thorsten Schöning,

4

Non sono esattamente sicuro di come il tempo di rendering 'test' dei tuoi test venga utilizzato come script java. Tuttavia, considera questo

Una pagina sul tuo sito è 50k che non è irragionevole. L'utente si trova sulla costa orientale mentre il server si trova a ovest. MTU non è sicuramente 10k, quindi ci saranno alcuni viaggi avanti e indietro. Potrebbero essere necessari 1/2 secondo per ricevere la tua pagina e i tuoi fogli di stile. Tipicamente (per me) javascript (tramite plugin jquery e simili) sono molto più che CSS. C'è anche quello che succede quando la tua connessione a Internet si blocca a metà della pagina, ma lascia che lo ignori (capita a me di tanto in tanto e credo che il css si renda, ma non ne sono sicuro al 100%).

Poiché css è in testa, potrebbero esserci connessioni aggiuntive per ottenerlo, il che significa che potenzialmente può finire prima della pagina. Comunque durante il tipo prende il resto della pagina e i file javascript (che sono molti più byte) la pagina non viene modificata, il che rende il sito / la connessione sembrano lenti.

ANCHE SE l'interprete JS rifiuta di avviarsi fino a quando il CSS non ha terminato il tempo impiegato per scaricare il codice javascript, specialmente quando il server sta tagliando il tempo in CSS, il che renderà il sito non carino.

È una piccola ottimizzazione ma questo è il motivo.


1
il server si trova sulla costa orientale, in seguito. Apparentemente, inoltre, non sei consapevole del fatto che ora usano un CDN.
jcolebrand,

3

Ecco un SINTESI di tutte le principali risposte sopra (o forse sotto in seguito :)

Per i browser moderni, inserisci CSS dove preferisci. Analizzerebbero il tuo file HTML (che chiamano analisi speculativa ) e inizierebbero a scaricare CSS in parallelo con l'analisi HTML.

Per i vecchi browser continua a mettere in primo piano i CSS (se non vuoi mostrare prima una pagina nuda ma interattiva).

Per tutti i browser, inserisci javascript il più in basso possibile nella pagina, poiché interromperà l'analisi del tuo codice HTML. Preferibilmente, scaricalo in modo asincrono (ovvero, chiamata ajax)

Ci sono anche alcuni risultati sperimentali per un caso particolare che afferma di mettere il javascript al primo posto (al contrario della tradizionale saggezza di mettere il CSS al primo posto) offre prestazioni migliori ma non viene fornito alcun ragionamento logico e manca di convalida sull'applicabilità diffusa, quindi puoi ignoralo per ora.

Quindi, per rispondere alla domanda: Sì. La raccomandazione di includere il CSS prima di JS non è valida per i browser moderni. Metti CSS dove vuoi e metti JS verso la fine, il più possibile.


1

Steve Souders ha già dato una risposta definitiva ma ...

Mi chiedo se ci sia un problema sia con il test originale di Sam che con la ripetizione di Josh.

Entrambi i test sembrano essere stati eseguiti su connessioni a bassa latenza in cui la configurazione della connessione TCP avrà un costo insignificante.

In che modo ciò influisce sul risultato del test non sono sicuro e vorrei guardare le cascate per i test su una connessione di latenza "normale" ma ...

Il primo file scaricato dovrebbe ottenere la connessione utilizzata per la pagina html e il secondo file scaricato otterrà la nuova connessione. (Svuotare i primi altera quella dinamica, ma qui non si fa)

Nei browser più recenti la seconda connessione TCP viene aperta in modo speculativo, quindi l'overhead della connessione viene ridotto / scompare, nei browser più vecchi ciò non è vero e la seconda connessione avrà l'overhead dell'apertura.

Non so come / se ciò influisca sull'esito dei test.


non seguire, a meno che non si abbia un pipelining che è incredibilmente raro, è molto improbabile che venga ridotta la configurazione della connessione ... d'accordo sul fatto che il test dovrebbe essere ripetuto a bassa latenza
Sam Saffron

Se guardi questa cascata puoi vedere dove Chrome apre speculativamente una seconda connessione prima che sia necessaria webpagetest.org/result/… (IE9 fa lo stesso) ... Stavo pensando a una latenza normale per scopi TCP piuttosto che bassa - che tipo di ambiente è stato eseguito il test?
Andy Davies,

2
Ri: "Steve Souders ha già dato una risposta definitiva ma ..." La cosa con l'evoluzione del web è che non ci sono risposte definitive. :) Ci sono 3-4 modi per caricare script e le cose cambiano. La semantica corretta in realtà avrebbe dovuto essere per Steve dire "Metti CSS prima di JavaScript sincrono" Altrimenti le persone sbagliano generalizzando perché è una regola per tutti gli script ...
hexalys,

Sì, ma la maggior parte delle persone include solo gli script in modo sincrono, quindi il consiglio di Steve è buono per chi non lo sapesse.
Andy Davies,

1

Penso che questo non sarà vero per tutti i casi. Perché css scaricherà parallelamente ma js non può. Considerare per lo stesso caso,

Invece di avere un singolo CSS, prendi 2 o 3 file CSS e provalo in questi modi,

1) css..css..js 2) css..js..css 3) js..css..css

Sono sicuro che css..css..js darà risultati migliori di tutti gli altri.


0

Dobbiamo tenere presente che i nuovi browser hanno funzionato sui loro motori Javascript, i loro parser e così via, ottimizzando i problemi di codice e markup comuni in un modo che i problemi riscontrati nei browser antichi come <= IE8 non sono più rilevanti, non solo con per quanto riguarda il markup ma anche l'uso di variabili JavaScript, selettori di elementi ecc. Posso vedere in un futuro non così lontano una situazione in cui la tecnologia ha raggiunto un punto in cui le prestazioni non sono più un problema.


Le prestazioni sono sempre un problema. Quasi quasi ignoro che esistono browser che non seguono le specifiche. Preparo semplicemente il mio codice in modo tale che quelli che seguono le specifiche funzionino a tutta velocità e gli altri lo faccio in modo tale che funzioni. Quindi, ad esempio, se funziona solo in IE8, tutto ok.
brunoais,

-5

Personalmente, non darei troppa enfasi a tale "saggezza popolare". Ciò che potrebbe essere stato vero in passato potrebbe non essere vero ora. Suppongo che tutte le operazioni relative all'interpretazione e al rendering di una pagina Web siano completamente asincrone ("recuperare" qualcosa e "agire su di esso" sono due cose completamente diverse che potrebbero essere gestite da thread diversi, ecc. ) E in ogni caso completamente al di fuori del tuo controllo o delle tue preoccupazioni.

Metterei riferimenti CSS nella parte "head" del documento, insieme a qualsiasi riferimento a script esterni. (Alcuni script potrebbero richiedere di essere inseriti nel corpo e, in tal caso, obbligarli.)

Oltre a questo ... se osservi che "questo sembra essere più veloce / più lento di quello, su questo / quel browser", considera questa osservazione come una curiosità interessante ma irrilevante e non lasciare che influenzi le tue decisioni di progettazione. Troppe cose cambiano troppo in fretta. (Qualcuno vuole scommettere su quanti minuti ci vorranno prima che il team di Firefox esca con l'ennesima versione provvisoria del loro prodotto? Sì, neanche io.)

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.