在网上无数的地方,我都看到过在JavaScript之前使用CSS的建议。推理一般是这样的:

当涉及到CSS和JavaScript的排序时,你需要你的CSS 先来。原因是呈现线程拥有所有的 样式显示页面所需的信息。如果JavaScript include首先出现,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&amp;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和ie浏览器上得到了类似的结果。然而,在Opera中,顺序并不重要。

似乎发生的情况是,JavaScript解释器在下载所有CSS之前拒绝启动。因此,首先使用JavaScript包含似乎更有效,因为JavaScript线程获得了更多的运行时间。

我遗漏了什么吗?把CSS include放在JavaScript include之前的建议是不正确的吗?

显然,我们可以添加async或使用setTimeout来释放呈现线程,或将JavaScript代码放在页脚中,或使用JavaScript加载器。这里的重点是关于基本JavaScript位和CSS位在头部的排序。


当前回答

我不会过分强调你们已经取得的成果。我相信这是主观的,但我有理由向你解释,在JavaScript之前放CSS更好。

在你的网站加载过程中,你会看到两种情况:

案例1:白屏→无风格网站→风格网站→互动→风格互动网站

案例2:白屏→无风格网站→互动→有风格网站→有风格和互动网站

我真的无法想象有人会选择情形二。这意味着使用慢速互联网连接的访问者将面对一个无风格的网站,允许他们使用JavaScript与之交互(因为JavaScript已经加载了)。此外,花在看一个无风格的网站上的时间将以这种方式最大化。为什么会有人想要那样?

它还可以更好地工作,正如jQuery所述:

“当使用依赖于CSS样式属性值的脚本时, 引用外部样式表或嵌入样式非常重要 元素”。

当文件以错误的顺序加载时(首先是JavaScript,然后是CSS),依赖于CSS文件中设置的属性的任何JavaScript代码(例如,div的宽度或高度)将无法正确加载。似乎在错误的加载顺序下,JavaScript“有时”知道正确的属性(也许这是由竞态条件引起的?)根据使用的浏览器,这种效果似乎更大或更小。

其他回答

就我个人而言,我不会过分强调这种“民间智慧”。过去可能是正确的事情现在很可能不正确。我认为所有与网页解释和呈现相关的操作都是完全异步的(“获取”和“对其进行操作”是两件完全不同的事情,可能由不同的线程处理,等等),并且在任何情况下都完全超出你的控制或关注。

我将CSS引用放在文档的“头部”部分,以及对外部脚本的任何引用。(有些脚本可能要求放在主体中,如果是这样,就满足他们的要求。)

除此之外……如果您观察到“在这个/那个浏览器上,这个似乎比那个更快/更慢”,请将此观察视为有趣但无关紧要的好奇心,不要让它影响您的设计决策。太多的事情变化太快。(有人想打赌Firefox团队会在多长时间内发布他们产品的另一个临时版本吗?是的,我也是。)

以下是之前所有主要答案的总结:

对于现代浏览器,可以将CSS内容放在您喜欢的任何地方。他们会分析您的HTML文件(他们称之为推测性解析),并在HTML解析的同时开始下载CSS。

对于旧的浏览器,继续将CSS放在最上面(如果您不想首先显示一个裸露但交互式的页面)。

对于所有浏览器,请将JavaScript内容放在页面上尽可能靠后的位置,因为这会暂停HTML的解析。最好是异步下载(即Ajax调用)。

也有一些实验结果表明,JavaScript优先(与传统的CSS优先相反)可以提供更好的性能,但没有给出任何逻辑推理,也缺乏广泛适用性的验证,所以现在可以忽略它。

所以,回答这个问题:是的。在JavaScript之前包含CSS的建议对于现代浏览器是无效的。把CSS放在你喜欢的任何地方,尽可能把JavaScript放在最后。

您的测试是在您的个人计算机上执行的,还是在web服务器上执行的?它是一个空白的页面,还是一个包含图像、数据库等的复杂在线系统?你的脚本是执行一个简单的悬停事件动作,还是你的网站呈现和与用户交互的核心组件?这里有几件事需要考虑,当你冒险进行高水平的web开发时,这些建议的相关性几乎总是成为规则。

“将样式表放在顶部,脚本放在底部”规则的目的是,在一般情况下,这是实现最佳渐进式呈现的最佳方法,这对用户体验至关重要。

撇开其他因素不谈:假设您的测试是有效的,并且您的测试结果确实与流行规则相反,这并不令人惊讶,真的。每个网站(以及让整个网站出现在用户屏幕上的所有内容)都是不同的,互联网也在不断发展。

我认为这并不适用于所有情况。因为CSS内容可以并行下载,但JavaScript代码不能。考虑相同的情况:

与其只有一段CSS内容,不如拿出两三个CSS文件,然后试试这些方法,

CSS . . CSS . . JavaScript CSS . . JavaScript . . CSS JavaScript . . CSS . . CSS

我确定CSS..CSS..JavaScript会给出比其他方法更好的结果。

2020年的答案是:这可能并不重要

这里最好的答案来自2012年,所以我决定自己测试一下。在Chrome for Android上,JS和CSS资源是并行下载的,我无法检测到页面渲染速度的差异。

我在博客上写了一篇更详细的文章