968 Stimmen

Sollte CSS immer vor JavaScript stehen?

An unzähligen Stellen im Internet habe ich die Empfehlung gesehen, CSS vor JavaScript einzubinden. Die Argumentation ist im Allgemeinen, in dieser Form :

Wenn es darum geht, Ihr CSS und JavaScript zu ordnen, sollten Sie Ihr CSS an erster Stelle stehen. Der Grund dafür ist, dass der Rendering-Thread über alle Stilinformationen hat, die er zum Rendern der Seite benötigt. Wenn die JavaScript zuerst kommt, muss die JavaScript-Engine alles parsen, bevor sie bevor sie mit der nächsten Gruppe von Ressourcen fortfährt. Das bedeutet, dass der Rendering Thread kann die Seite nicht vollständig anzeigen, da er nicht über alle Stile, die er benötigt.

Mein aktueller Test zeigt etwas ganz anderes:

Mein Test-Kabelbaum

Ich verwende Folgendes Rubinrot Skript, um spezifische Verzögerungen für verschiedene Ressourcen zu erzeugen:

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..."
}

Der obige Miniserver erlaubt es mir, beliebige Verzögerungen für JavaScript-Dateien (sowohl Server als auch Client) und beliebige CSS-Verzögerungen einzustellen. Zum Beispiel, http://10.0.0.50:8081/test.css?delay=500 gibt mir eine Verzögerung von 500 ms bei der Übertragung des CSS.

Ich verwende die folgende Seite zum Testen.

<!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>

Wenn ich das CSS zuerst einfüge, braucht die Seite 1,5 Sekunden zum Rendern:

CSS first

Wenn ich das JavaScript zuerst einfüge, braucht die Seite 1,4 Sekunden zum Rendern:

JavaScript first

Ich erhalte ähnliche Ergebnisse in Chrome, Firefox und Internet Explorer. Unter Oper Die Reihenfolge spielt jedoch keine Rolle.

Es scheint so zu sein, dass der JavaScript-Interpreter sich weigert zu starten, bis alle CSS heruntergeladen sind. Es scheint also, dass es effizienter ist, JavaScript zuerst einzubinden, da der JavaScript-Thread mehr Laufzeit erhält.

Habe ich etwas verpasst? Ist die Empfehlung, CSS-Includes vor JavaScript-Includes zu platzieren, nicht korrekt?

Es ist klar, dass wir async hinzufügen oder setTimeout verwenden könnten, um den Render-Thread freizugeben, oder den JavaScript-Code in die Fußzeile stellen oder einen JavaScript-Loader verwenden könnten. Hier geht es um die Anordnung der wesentlichen JavaScript- und CSS-Bits im Kopf.

11voto

Salman A Punkte 246207

Aktualisiert 2017-12-16

Ich war mir bei den Tests im OP nicht sicher. Ich beschloss, ein wenig zu experimentieren, und räumte mit einigen Mythen auf.

Synchrone <script src...> wird das Herunterladen der Ressourcen blockiert bis sie heruntergeladen und ausgeführt wird

Dies ist nicht mehr der Fall . Werfen Sie einen Blick auf den von Chrome 63 erzeugten Wasserfall:

<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>

Chrome net inspector -> waterfall

<link rel=stylesheet> blockiert nicht den Download und die Ausführung von Skripten unter ihm

Dies ist falsch . Die Formatvorlage wird den Download nicht blockieren, aber sie wird die Ausführung des Skripts blockieren ( kleine Erklärung hier ). Werfen Sie einen Blick auf das von Chrome 63 generierte Leistungsdiagramm:

<link href="http://stackoverflow.com//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>

Chrome dev tools -> performance


Unter Berücksichtigung der obigen Ausführungen lassen sich die Ergebnisse im OP wie folgt erklären:

CSS zuerst:

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

JavaScript zuerst:

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

11voto

Ted Cohen Punkte 968

Ist die Empfehlung, CSS vor JavaScript einzubinden, ungültig?

Nicht, wenn Sie es einfach als Empfehlung betrachten. Aber wenn Sie es als eine harte und schnelle Regel betrachten, ist es ungültig.

En Fenster: DOMContentLoaded-Ereignis :

Das Laden von Stylesheets blockiert die Skriptausführung, wenn Sie also ein <script> nach einer <link rel="stylesheet" ...> die Seite wird nicht fertig geparst

  • und DOMContentLoaded werden nicht ausgelöst, bis das Stylesheet geladen ist.

Es scheint, dass Sie wissen müssen, wovon jedes Skript abhängt, und sicherstellen müssen, dass die Ausführung des Skripts bis nach dem richtigen Abschlussereignis verzögert wird. Wenn sich das Skript nur auf die DOM kann es in ondomready/domcontentloaded fortgesetzt werden. Wenn es auf Bilder geladen werden oder Stylesheets angewendet werden, dann, wenn ich die obige Referenz richtig gelesen, dass Code muss bis zum onload-Ereignis verschoben werden.

Ich glaube nicht, dass eine Sockengröße für alle passt, auch wenn sie so verkauft werden, und ich weiß, dass eine Schuhgröße nicht für alle passt. Ich glaube nicht, dass es eine endgültige Antwort auf die Frage gibt, was man zuerst laden sollte, Stile oder Schrift. Es ist eher eine Entscheidung von Fall zu Fall, was in welcher Reihenfolge geladen werden muss und was auf später verschoben werden kann, da es nicht auf dem "kritischen Pfad" liegt.

Um dem Beobachter zu antworten, der meinte, es sei besser, die Interaktionsmöglichkeiten der Benutzer zu verzögern, bis das Blatt schön ist. Es gibt viele von Ihnen da draußen und Sie ärgern Ihre Kollegen, die das Gegenteil denken. Sie sind auf eine Website gekommen, um einen Zweck zu erfüllen, und Verzögerungen bei der Interaktion mit einer Website, während sie darauf warten, dass Dinge, die nicht wichtig sind, fertig geladen werden, sind sehr frustrierend. Ich sage nicht, dass Sie im Unrecht sind, sondern nur, dass Sie sich bewusst sein sollten, dass es eine andere Fraktion gibt, die Ihre Prioritäten nicht teilt.

Diese Frage gilt insbesondere für alle Anzeigen, die auf Websites geschaltet werden. Ich würde es toll finden, wenn Website-Autoren nur Platzhalter darstellen würden divs für den Anzeigeninhalt und stellten sicher, dass ihre Website geladen und interaktiv war, bevor sie die Anzeigen in einem Onload-Ereignis einfügten. Selbst dann würde ich gerne sehen, dass die Anzeigen nacheinander geladen werden, anstatt alle auf einmal, weil sie meine Fähigkeit beeinträchtigen, den Inhalt der Website zu scrollen, während die aufgeblähten Anzeigen geladen werden. Aber das ist nur die Sichtweise eines Einzelnen.

  • Sie kennen Ihre Nutzer und wissen, worauf sie Wert legen.
  • Kennen Sie Ihre Nutzer und die von ihnen verwendete Browserumgebung.
  • Sie müssen wissen, was die einzelnen Dateien bewirken und welche Voraussetzungen sie erfüllen müssen. Dass alles funktioniert, hat Vorrang vor Geschwindigkeit und Schönheit.
  • Verwenden Sie Tools, die Ihnen bei der Entwicklung die Zeitachse des Netzes anzeigen.
  • Testen Sie in jeder der Umgebungen, die Ihre Benutzer verwenden. Es kann erforderlich sein, die Reihenfolge des Ladens dynamisch (serverseitig, bei der Erstellung der Seite) je nach Benutzerumgebung zu ändern.
  • Im Zweifelsfall ändern Sie die Reihenfolge und messen erneut.
  • Es ist möglich, dass die Mischung von Stilen und Skripten in der Ladereihenfolge optimal ist; nicht alles von dem einen und alles von dem anderen.
  • Experimentieren Sie nicht nur mit der Reihenfolge, in der die Dateien geladen werden sollen, sondern auch mit dem Ort. _Kopf_ ? Unter Körper ? Nach Körper ? DOM Bereit/Leer? Geladen?
  • Ziehen Sie gegebenenfalls asynchrone und aufgeschobene Optionen in Betracht, um die Nettoverzögerung zu verringern, die der Benutzer erfährt, bevor er mit der Seite interagieren kann. Testen Sie, um festzustellen, ob sie helfen oder schaden.
  • Bei der Bewertung der optimalen Ladungsreihenfolge gibt es immer Kompromisse zu berücksichtigen. Hübsch vs. reaktionsschnell nur eine zu sein.

6voto

Ben McCann Punkte 17571

Die Antwort für 2020: Es spielt wahrscheinlich keine Rolle

Die beste Antwort stammt aus dem Jahr 2012, also habe ich beschlossen, es selbst zu testen. Bei Chrome für Android werden die JS- und CSS-Ressourcen parallel heruntergeladen, und ich konnte keinen Unterschied in der Geschwindigkeit der Seitenwiedergabe feststellen.

Ich habe eine Ausführlicherer Bericht in meinem Blog

4voto

Ich bin mir nicht ganz sicher, wie Sie die "Rendering"-Zeit testen, da Sie JavaScript verwenden. Allerdings, beachten Sie diese:

Eine Seite auf Ihrer Website ist 50 kB groß, was nicht unangemessen ist. Der Benutzer ist auf der Ostküste während sich Ihr Server im Westen befindet. MTU ist definitiv keine 10.000 Euro wert, also wird es ein paar Fahrten hin und her geben. Es kann 1/2 Sekunde dauern, bis Ihre Seite und die Formatvorlagen empfangen werden. Normalerweise wird (bei mir) JavaScript (über jQuery Plugin und so weiter) sind viel mehr als CSS. Es gibt auch das, was passiert, wenn Ihre Internetverbindung mitten auf der Seite abbricht, aber lassen wir das mal außer Acht (das passiert mir gelegentlich, und ich glaube, dass das CSS gerendert wird, aber ich bin mir nicht 100 % sicher).

Da CSS in _Kopf_ Wenn die Seite nicht auf dem Bildschirm angezeigt wird, kann es zusätzliche Verbindungen geben, was bedeutet, dass sie möglicherweise vor der Seite beendet werden kann. Wie auch immer, während der Typ der Rest der Seite nimmt und die JavaScript-Dateien (die viele weitere Bytes ist) die Seite ist unstyled, die die Website / Verbindung langsam erscheinen lässt.

Auch wenn Der JavaScript-Interpreter weigert sich, zu starten, bevor das CSS fertig ist. Die Zeit, die für das Herunterladen des JavaScript-Codes benötigt wird, vor allem, wenn er weit vom Server entfernt ist, beeinträchtigt die Zeit für das CSS, was dazu führt, dass die Website nicht schön aussieht.

Es ist eine kleine Optimierung, aber das ist der Grund dafür.

3voto

mehmet Punkte 6723

Hier ist ein Zusammenfassung aller bisherigen wichtigen Antworten:

Bei modernen Browsern können Sie den CSS-Inhalt dort platzieren, wo Sie ihn haben möchten. Sie würden Ihre HTML-Datei analysieren (die sie als spekulatives Parsing ) und starten Sie das Herunterladen von CSS parallel zur HTML-Analyse.

Bei älteren Browsern sollten Sie das CSS weiterhin ganz oben platzieren (wenn Sie nicht zuerst eine nackte, aber interaktive Seite anzeigen wollen).

Bei allen Browsern sollten Sie den JavaScript-Inhalt so weit unten auf der Seite wie möglich platzieren, da er das Parsen Ihres HTML-Satzes unterbricht. Laden Sie es vorzugsweise asynchron herunter (d. h. ein Ajax Aufruf).

Es gibt auch einige experimentelle Ergebnisse für einen bestimmten Fall, in dem behauptet wird, dass die Verwendung von JavaScript an erster Stelle (im Gegensatz zur traditionellen Weisheit, CSS an die erste Stelle zu setzen) zu einer besseren Leistung führt, aber es wird keine logische Begründung dafür gegeben, und es fehlt eine Validierung hinsichtlich einer weit verbreiteten Anwendbarkeit, also können Sie es vorerst ignorieren.

Also, um die Frage zu beantworten: Ja. Die Empfehlung, CSS vor JavaScript einzufügen, ist für die modernen Browser ungültig. Fügen Sie CSS ein, wo immer Sie wollen, und fügen Sie JavaScript nach Möglichkeit am Ende ein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X