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.

1voto

Andy Davies Punkte 5767

Steve Souders hat bereits eine endgültige Antwort gegeben, aber...

Ich frage mich, ob es ein Problem sowohl mit Sams ursprünglichem Test als auch mit Joshs Wiederholung davon gibt.

Beide Tests scheinen mit Verbindungen mit geringer Latenz durchgeführt worden zu sein, bei denen der Aufbau der TCP-Verbindung nur geringfügige Kosten verursacht.

Wie sich das auf das Testergebnis auswirkt, weiß ich nicht, und ich würde mir die Wasserfälle für die Tests über eine "normale" Latenzverbindung ansehen wollen, aber...

Die erste heruntergeladene Datei debe die für die HTML-Seite verwendete Verbindung, und die zweite heruntergeladene Datei erhält die neue Verbindung. (Ein frühes Flushen des <head> ändert diese Dynamik, aber das wird hier nicht gemacht).

In neueren Browsern wird die zweite TCP-Verbindung spekulativ geöffnet, so dass der Verbindungs-Overhead reduziert wird bzw. wegfällt. In älteren Browsern ist dies nicht der Fall, und die zweite Verbindung hat den Overhead, geöffnet zu werden.

Ob und wie sich dies auf das Ergebnis der Tests auswirkt, weiß ich nicht genau.

1voto

harishkumar329 Punkte 1200

Ich denke, dass dies nicht in allen Fällen der Fall sein wird. Denn der CSS-Inhalt wird parallel heruntergeladen, aber der JavaScript-Code nicht. Betrachten wir den gleichen Fall:

Nehmen Sie statt eines einzigen CSS-Inhalts zwei oder drei CSS-Dateien und probieren Sie sie auf diese Weise aus,

  1. CSS..CSS..JavaScript

  2. CSS..JavaScript..CSS

  3. JavaScript..CSS..CSS

Ich bin sicher, dass CSS..CSS..JavaScript ein besseres Ergebnis als alle anderen liefern wird.

0voto

George Katsanos Punkte 12989

Wir müssen bedenken, dass die neuen Browser an ihren JavaScript-Engines, ihren Parsern usw. gearbeitet haben, um häufige Code- und Markup-Probleme so zu optimieren, dass Probleme, die in alten Browsern wie Internet Explorer 8 oder früher sind nicht mehr relevant, nicht nur in Bezug auf das Markup, sondern auch auf die Verwendung von JavaScript-Variablen, Elementselektoren usw.

Ich kann mir vorstellen, dass die Technologie in nicht allzu ferner Zukunft einen Punkt erreicht hat, an dem die Leistung keine Rolle mehr spielt.

-5voto

user106701 Punkte 175

Persönlich, Auf solche "Volksweisheiten" würde ich nicht allzu viel Wert legen. Was in der Vergangenheit wahr gewesen sein mag, muss nicht unbedingt auch heute gelten. Ich würde davon ausgehen, dass alle Vorgänge im Zusammenhang mit der Interpretation und Darstellung einer Webseite vollständig asynchron ablaufen ("etwas abrufen" und "darauf reagieren" sind zwei völlig unterschiedliche Dinge, die von verschiedenen Threads bearbeitet werden können, usw. ), und in jedem Fall außerhalb Ihrer Kontrolle oder Ihrer Sorge.

Ich würde die CSS-Verweise in den "Kopf"-Teil des Dokuments setzen, zusammen mit allen Verweisen auf externe Skripte. (Einige Skripte können verlangen, dass sie im Textkörper platziert werden, und wenn dies der Fall ist, sollten Sie ihnen nachkommen).

Darüber hinaus ... wenn Sie feststellen, dass "dies schneller/langsamer als jenes zu sein scheint, auf diesem/diesem Browser", behandeln Sie diese Beobachtung als eine interessante, aber irrelevante Neugierde und lassen Sie sich bei Ihren Designentscheidungen nicht davon beeinflussen. Zu viele Dinge ändern sich zu schnell. (Möchte jemand Wetten abschließen, wie viele Minuten dauert es, bis das Firefox-Team eine weitere Zwischenversion seines Produkts herausbringt? Ja, ich auch nicht.)

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