【发布时间】:2012-03-05 11:45:15
【问题描述】:
在网上的无数地方,我都看到了在 JavaScript 之前包含 CSS 的建议。推理一般是,of this form:
在订购 CSS 和 JavaScript 时,您需要自己的 CSS 先来。原因是渲染线程拥有所有 呈现页面所需的样式信息。如果 JavaScript 包含在先,JavaScript引擎必须先解析它 继续下一组资源。这意味着渲染 线程不能完全显示页面,因为它没有所有 它需要的样式。
我的实际测试揭示了一些完全不同的东西:
我的测试工具
我使用以下 Ruby 脚本为各种资源生成特定的延迟:
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..."
}
上面的迷你服务器允许我为 JavaScript 文件(服务器和客户端)设置任意延迟和任意 CSS 延迟。例如,http://10.0.0.50:8081/test.css?delay=500 给了我 500 毫秒的 CSS 传输延迟。
我使用以下页面进行测试。
<!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&jsdelay=1000"></script>
</head>
<body>
<p>
Elapsed time is:
<script type='text/javascript'>
document.write(new Date() - startTime);
</script>
</p>
</body>
</html>
当我首先包含 CSS 时,页面需要 1.5 秒才能呈现:
当我首先包含 JavaScript 时,页面需要 1.4 秒才能呈现:
我在 Chrome、Firefox 和 Internet Explorer 中得到了类似的结果。然而,在 Opera 中,顺序并不重要。
似乎正在发生的事情是,JavaScript 解释器在所有 CSS 下载完成之前拒绝启动。因此,似乎先包含 JavaScript 会更有效,因为 JavaScript 线程会获得更多运行时间。
我是否遗漏了什么,将 CSS 包含在 JavaScript 包含之前的建议是否不正确?
很明显,我们可以添加异步或使用 setTimeout 来释放渲染线程或将 JavaScript 代码放在页脚中,或者使用 JavaScript 加载器。这里的重点是关于头部中基本 JavaScript 位和 CSS 位的排序。
【问题讨论】:
-
1511 与 1422 的差异是否具有统计学意义?那是百分之六。显着与平均人类表现差异的一般阈值约为 20%。
-
重点是重新排序消除了这种任意延迟,您可以将延迟设置为您想要的任何内容,它只是问题的演示。
-
你的延迟是 100 毫秒吗?您的屏幕截图中的差异是 89 毫秒。在您的 URL 中,它是
delay=400&amp;jsdelay=1000和delay=500,这与 100 毫秒或 89 毫秒相差甚远。我想我不清楚你指的是哪些数字。 -
"如果 Javascript 包含在前,则 Javascript 引擎必须在继续处理下一组资源之前将其全部解析。这意味着渲染线程无法完全显示页面,因为它没有它需要的所有样式。” - 如果 JS 包含在头部,那么 JS 将在页面呈现之前执行,无论 CSS 包含是在之前还是之后。跨度>
-
不确定您是否考虑过这一点,但加载时间的感知也很重要。因此,例如,如果首先加载 CSS 甚至只为您提供页面背景颜色/纹理,它似乎会更快。绝对加载时间可能无法说明这一点。
标签: javascript css performance