Monday, June 4, 2018

Is the recommendation to include CSS before JavaScript invalid?



In countless places online I have seen the recommendation to include CSS prior to JavaScript. The reasoning is generally, of this form:




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.




My actual testing reveals something quite different:



My test harness




I use the following Ruby script to generate specific delays for various resources:



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

}


The above mini server allows me to set arbitrary delays for JavaScript files (both server and client) and arbitrary CSS delays. For example, http://10.0.0.50:8081/test.css?delay=500 gives me a 500 ms delay transferring the CSS.



I use the following page to test.







test






Elapsed time is:







When I include the CSS first, the page takes 1.5 seconds to render:




CSS first



When I include the JavaScript first, the page takes 1.4 seconds to render:



JavaScript first



I get similar results in Chrome, Firefox and Internet Explorer. In Opera however, the ordering simply does not matter.



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.




Am I missing something, is the recommendation to place CSS includes prior to JavaScript includes not correct?



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.


Answer



This is a very interesting question. I've always put my CSS s before my JS











js.html







CSS first












test.js



var jsload = Date.now();



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


jquery.js was jquery-1.7.1.min.js


No comments:

Post a Comment

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...