Note that there are some explanatory texts on larger screens.

plurals
  1. POIs the recommendation to include CSS before JavaScript invalid?
    text
    copied!<p>In countless places online I have seen the recommendation to include CSS prior to JavaScript. The reasoning is generally, <a href="https://stackoverflow.com/questions/6005827/what-can-i-do-to-decrease-load-times-of-html-pages/6005832#6005832">of this form</a>:</p> <blockquote> <p>When it comes to ordering your CSS and JavaScript, you want your CSS to come first. The reason is that the rendering thread has all the style information it needs to render the page. If the JavaScript includes come first, the JavaScript engine has to parse it all before continuing on to the next set of resources. This means the rendering thread can't completely show the page, since it doesn't have all the styles it needs.</p> </blockquote> <p>My actual testing reveals something quite different: </p> <h3>My test harness</h3> <p>I use the following Ruby script to generate specific delays for various resources: </p> <pre><code>require 'rubygems' require 'eventmachine' require 'evma_httpserver' require 'date' class Handler &lt; 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("&amp;").map{|s| s.split("=")}.flatten parsed = Hash[*array] delay = parsed["delay"].to_i / 1000.0 jsdelay = parsed["jsdelay"].to_i delay = 5 if (delay &gt; 5) jsdelay = 5000 if (jsdelay &gt; 5000) delay = 0 if (delay &lt; 0) jsdelay = 0 if (jsdelay &lt; 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 &lt; #{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..." } </code></pre> <p>The above mini server allows me to set arbitrary delays for JavaScript files (both server and client) and arbitrary CSS delays. For example, <code>http://10.0.0.50:8081/test.css?delay=500</code> gives me a 500&nbsp;ms delay transferring the CSS. </p> <p>I use the following page to test.</p> <pre><code>&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;test&lt;/title&gt; &lt;script type='text/javascript'&gt; var startTime = new Date(); &lt;/script&gt; &lt;link href="http://10.0.0.50:8081/test.css?delay=500" type="text/css" rel="stylesheet"&gt; &lt;script type="text/javascript" src="http://10.0.0.50:8081/test2.js?delay=400&amp;amp;jsdelay=1000"&gt;&lt;/script&gt; &lt;/head&gt; &lt;body&gt; &lt;p&gt; Elapsed time is: &lt;script type='text/javascript'&gt; document.write(new Date() - startTime); &lt;/script&gt; &lt;/p&gt; &lt;/body&gt; &lt;/html&gt; </code></pre> <p>When I include the CSS first, the page takes 1.5&nbsp;seconds to render: </p> <p><img src="https://i.stack.imgur.com/ZDgrs.png" alt="CSS first"></p> <p>When I include the JavaScript first, the page takes 1.4&nbsp;seconds to render: </p> <p><img src="https://i.stack.imgur.com/5o5SG.png" alt="JavaScript first"></p> <p>I get similar results in Chrome, Firefox and Internet&nbsp;Explorer. In Opera however, the ordering simply does not matter.</p> <p>What appears to be happening is that the JavaScript interpreter refuses to start until all the CSS is downloaded. So, it seems that having JavaScript includes first is more efficient as the JavaScript thread gets more run time. </p> <p>Am I missing something, is the recommendation to place CSS includes prior to JavaScript includes not correct? </p> <p><sub>It is clear that we could add async or use setTimeout to free up the render thread or put the JavaScript code in the footer, or use a JavaScript loader. The point here is about ordering of essential JavaScript bits and CSS bits in the head.</sub></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload