CSS是否应始终优先于Javascript?


897

在网上的无数地方,我看到了建议在JavaScript之前加入CSS。推理通常采用以下形式

在订购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&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秒的时间来呈现:

CSS优先

当我首先包含JavaScript时,页面需要1.4秒的时间呈现:

JavaScript优先

我在Chrome,Firefox和Internet Explorer中得到了类似的结果。但是,在Opera中,排序根本没有关系。

似乎正在发生的事情是JavaScript解释器拒绝启动,直到所有CSS被下载为止。因此,随着JavaScript线程获得更多的运行时间,似乎首先包含JavaScript会更有效。

我是否遗漏了一些东西,建议将CSS包含放在JavaScript包含之前是不正确的?

显然,我们可以添加异步或使用setTimeout释放渲染线程或将JavaScript代码放在页脚中,或使用JavaScript加载器。这里的重点是关于头部中必需的JavaScript位和CSS位的排序。


120
1511和1422有统计显着性差异吗?那是6%。人与人之间显着绩效差异的一般阈值约为20%。
Jeff Atwood

15
关键是重新排序消除了这种任意延迟,您可以将延迟设置为所需的任何值,这只是问题的演示。
Sam Saffron '02

3
是您延迟100毫秒吗?屏幕截图的区别是89ms。在你的URL,就delay=400&amp;jsdelay=1000delay=500这是隔靴搔痒为100ms或89ms。我想我不清楚您指的是哪个数字。
Jeff Atwood

4
“如果首先包含Javascript,则Javascript引擎必须先解析所有内容,然后再继续下一组资源。这意味着呈现线程无法完全显示页面,因为它没有所需的所有样式。” -如果JS包含位于头部,那么无论页面的CSS包含之前还是之后,JS都会在呈现页面之前执行。
nnnnnn '02

162
不知道您是否考虑过这一点,但是加载时间的感知也很重要。因此,例如,如果首先加载CSS甚至只给您页面背景颜色/纹理,它似乎会更快。绝对加载时间可能并不表示这一点。
Rakesh Pai

Answers:


712

这是一个非常有趣的问题。我一直将CSS放在<link href="...">JS之前,<script src="...">因为“我读过一遍感觉更好。” 所以,你是对的。现在是时候进行实际研究了!

我在Node(下面的代码)中设置了自己的测试工具。基本上,我:

  • 确保没有HTTP缓存,以便浏览器每次加载页面时都必须进行完整下载。
  • 为了模拟现实,我包括了jQuery和H5BP CSS(因此可以解析大量的脚本/ CSS)
  • 设置两页-一页在脚本之前包含CSS,一页在脚本之后包含CSS。
  • 记录了中的外部脚本<head>执行所需的时间
  • 记录了内联脚本<body>执行所需的时间,类似于DOMReady
  • 将CSS和/或脚本发送到浏览器的时间延迟了500毫秒。
  • 在3种主要浏览器中进行20次测试。

结果

首先,将CSS文件延迟500毫秒:

     Browser: Chrome 18    | IE 9         | Firefox 9
         CSS: first  last  | first  last  | first last
=======================================================
Header Exec |              |              |
Average     | 583ms  36ms  | 559ms  42ms  | 565ms 49ms
St Dev      | 15ms   12ms  | 9ms    7ms   | 13ms  6ms
------------|--------------|--------------|------------
Body Exec   |              |              |
Average     | 584ms  521ms | 559ms  513ms | 565ms 519ms
St Dev      | 15ms   9ms   | 9ms    5ms   | 13ms  7ms

接下来,我将jQuery设置为延迟500ms而不是CSS:

     Browser: Chrome 18    | IE 9         | Firefox 9
         CSS: first  last  | first  last  | first last
=======================================================
Header Exec |              |              |
Average     | 597ms  556ms | 562ms  559ms | 564ms 564ms
St Dev      | 14ms   12ms  | 11ms   7ms   | 8ms   8ms
------------|--------------|--------------|------------
Body Exec   |              |              |
Average     | 598ms  557ms | 563ms  560ms | 564ms 565ms
St Dev      | 14ms   12ms  | 10ms   7ms   | 8ms   8ms

最后,我将jQuery和CSS 设置 500ms的延迟:

     Browser: Chrome 18    | IE 9         | Firefox 9
         CSS: first  last  | first  last  | first last
=======================================================
Header Exec |              |              |
Average     | 620ms  560ms | 577ms  577ms | 571ms 567ms
St Dev      | 16ms   11ms  | 19ms   9ms   | 9ms   10ms
------------|--------------|--------------|------------
Body Exec   |              |              |
Average     | 623ms  561ms | 578ms  580ms | 571ms 568ms
St Dev      | 18ms   11ms  | 19ms   9ms   | 9ms   10ms

结论

首先,请务必注意,我在假设<head>您的文档中有脚本(而不是末尾<body>)的情况下进行操作。关于为什么可能<head>在文档末尾与文档末尾链接到脚本的争论有很多,但这不在此答案的范围之内。这完全是关于<script>s 是否应该在<link>s 之前<head>

在现代的DESKTOP浏览器中,似乎首先链接到CSS 绝对不会提高性能。将CSS放在脚本之后可以在延迟CSS和脚本时获得微不足道的收益,但是在延迟CSS时可以带来很多收益。(由last第一组结果中的列显示。)

鉴于最后一次链接到CSS似乎并没有影响性能,但是在某些情况下可以带来收益,因此如果您不关心旧浏览器的性能,则应在仅在桌面浏览器上链接到外部脚本之后再链接到外部样式表阅读有关移动情况的信息。

为什么?

从历史上看,当浏览器遇到<script>指向外部资源的标记时,浏览器将停止解析HTML,检索脚本,执行脚本,然后继续解析HTML。相反,如果浏览器遇到<link>外部样式表的,它将在提取CSS文件的同时继续解析HTML(并行)。

因此,广为人知的建议是将样式表放在第一位-首先下载样式表,然后并行加载第一个下载的脚本。

但是,现代浏览器(包括我上面测试过的所有浏览器)已经实现了推测性解析,即浏览器以HTML形式“向前看”,并脚本下载和执行之前开始下载资源。

在没有推测性解析的旧浏览器中,将脚本放在第一位会影响性能,因为它们不会并行下载。

浏览器支持

投机解析首先在以下位置实现:(以及截至2012年1月使用该版本或更高版本的全球桌面浏览器用户所占的百分比)

  • Chrome 1(WebKit 525)(100%)
  • IE 8(75%)
  • Firefox 3.5(96%)
  • Safari 4(99%)
  • 歌剧11.60(85%)

总计目前使用的台式机浏览器中大约有85%支持推测性加载。将脚本放到CSS上将对全球 15%的用户造成性能损失;YMMV根据您网站的特定受众群体。(请记住,这个数字正在减少。)

在移动浏览器上,仅由于移动浏览器和OS的异构性不同,很难获得确切的数字。由于投机渲染是在WebKit 525(2008年3月发布)中实现的,并且几乎所有有价值的移动浏览器都基于WebKit,因此可以得出结论,“大多数”移动浏览器支持它。根据quirksmode,iOS 2.2 / Android 1.0使用WebKit525。我不知道Windows Phone的外观。

但是,我在Android 4设备上进行了测试,虽然看到的数字与台式机结果相似,但仍将其连接到Android版Chrome浏览中出色的新型远程调试器,并且“网络”标签显示浏览器实际上正在等待下载CSS,直到JavaScript完全加载为止-换句话说,即使最新版本的WebKit for Android也似乎不支持推测性解析。 我怀疑可能由于移动设备固有的CPU,内存和/或网络限制而将其关闭。

原谅草率–这是Q&D。

app.js

var express = require('express')
, app = express.createServer()
, fs = require('fs');

app.listen(90);

var file={};
fs.readdirSync('.').forEach(function(f) {
    console.log(f)
    file[f] = fs.readFileSync(f);
    if (f != 'jquery.js' && f != 'style.css') app.get('/' + f, function(req,res) {
        res.contentType(f);
        res.send(file[f]);
    });
});


app.get('/jquery.js', function(req,res) {
    setTimeout(function() {
        res.contentType('text/javascript');
        res.send(file['jquery.js']);
    }, 500);
});

app.get('/style.css', function(req,res) {
    setTimeout(function() {
        res.contentType('text/css');
        res.send(file['style.css']);
    }, 500);
});


var headresults={
    css: [],
    js: []
}, bodyresults={
    css: [],
    js: []
}
app.post('/result/:type/:time/:exec', function(req,res) {
    headresults[req.params.type].push(parseInt(req.params.time, 10));
    bodyresults[req.params.type].push(parseInt(req.params.exec, 10));
    res.end();
});

app.get('/result/:type', function(req,res) {
    var o = '';
    headresults[req.params.type].forEach(function(i) {
        o+='\n' + i;
    });
    o+='\n';
    bodyresults[req.params.type].forEach(function(i) {
        o+='\n' + i;
    });
    res.send(o);
});

css.html

<!DOCTYPE html>
<html>
    <head>
        <title>CSS first</title>
        <script>var start = Date.now();</script>
        <link rel="stylesheet" href="style.css">
        <script src="jquery.js"></script>
        <script src="test.js"></script>
    </head>
    <body>
        <script>document.write(jsload - start);bodyexec=Date.now()</script>
    </body>
</html>

js.html

<!DOCTYPE html>
<html>
    <head>
        <title>CSS first</title>
        <script>var start = Date.now();</script>
        <script src="jquery.js"></script>
        <script src="test.js"></script>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <script>document.write(jsload - start);bodyexec=Date.now()</script>
    </body>
</html>

test.js

var jsload = Date.now();


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

jquery.js是jquery-1.7.1.min.js


137
这是一个了不起的答案,感谢您使用科学!根据您的结果“在现代浏览器中,似乎先链接到CSS永远不会提高性能”,我认为问题标题的答案是“ 是”,而CSS first的旧建议显然是无效的。
Jeff Atwood

关于@ josh3736在移动设备上的逆向更新...这是一个例子,可以避免在这一重大变化上步履维艰。我很好奇其他移动浏览器的行为方式(webkit,壁虎,presto,三叉戟等),因为移动性能通常更为重要。
scunliffe 2012年

1
您还应该尝试增加一些速度来打印css / js,以模拟速度较慢的服务器的速度。
kirb 2012年

1
“首先,需要注意的重要一点是,我正在假设<head>您的文档中有脚本(而不是末尾<body>)。我会在答案的更早部分(如顶部)强调这一点。从几乎任何角度来看,包括一个指向外部文件的scriptin head几乎都是不正确的(肯定不是一种性能)。我不记得曾经在现实生活中这样做过。内联脚本可能只有一两行,但仅此而已。默认的,没有非常好的相反的原因,应该是身体的末端。
TJ Crowder

1
不赞成投票的jQuery不是JavaScript,它只会使页面更加膨胀,因此使用它的结果并不客观。
约翰

303

将CSS放在JavaScript之前有两个主要原因。

  1. 旧的浏览器(Internet Explorer 6-7,Firefox 2等)在开始下载脚本时会阻止所有后续下载。因此,如果您a.js之后依次b.css下载它们,请先下载:a然后b。如果您b.css关注a.js它们,则可以并行下载它们,从而使页面加载更快。

  2. 在下载所有样式表之前,不会呈现任何内容-在所有浏览器中都是如此。脚本是不同的-它们阻止呈现页面中script标记下方的所有DOM元素。如果将脚本放在HEAD中,则意味着整个页面都无法渲染,直到下载所有样式表和所有脚本为止。虽然可以阻止样式表的所有渲染(这样您就可以第一次获得正确的样式,并避免出现未样式化的内容FOUC),但阻止脚本的整个页面渲染却没有任何意义。通常,脚本不会影响任何DOM元素或仅影响DOM元素的一部分。最好将脚本加载到尽可能低的页面中,甚至更好地异步加载。

Cuzillion创建示例很有趣。例如,此页面的HEAD中有一个脚本,因此整个页面空白,直到完成下载为止。但是,如果将脚本移到BODY块的末尾,则页面标题将呈现,因为这些DOM元素位于SCRIPT标记上方,如您在此页面上所见。


10
尊敬史蒂夫打我的答案,但我会添加有关他提到什么的文章:stevesouders.com/blog/2009/04/27/...
胡安-帕布洛武里蒂卡

4
看看哪些浏览器支持的async属性,当他说“更好的装载它们异步”的史蒂夫在这里推荐- stackoverflow.com/questions/1834077/...
杰夫·阿特伍德

嘿,您能告诉我为什么有人用@import指令链接CSS文件吗?
Josh Stodola'2

6
2)的来源是什么,如果是真的,那么您能解释一下为什么有时页面会完成内容加载,然后再过一两秒钟应用CSS吗?(这种情况很少发生在我自己的CSS中位于<head>标记中的页面上)
Izkata 2012年

2
那么我们应该在页面末尾加上jQuery+ jQuery UI+ $(document).ready(function () { });吗?它会一直按预期工作吗?
奥利维尔·庞斯

42

我不会在您获得的结果上强调太多,我相信这是主观的,但是我有理由向您解释,最好将CSS放在js之前。

在加载网站期间,您会看到两种情况:

案例1:白屏>无样式的网站>样式化的网站>交互>样式化和交互式的网站

案例2:白屏>无样式的网站>交互性>样式化的网站>样式化和交互式的网站


我真的无法想象有人选择案例2。这意味着使用慢速互联网连接的访问​​者将面临一个无样式的网站,该网站允许他们使用Javascript与该网站进行互动(因为该网站已经加载)。此外,通过这种方式可以最大程度地增加花在浏览无样式网站上的时间。为什么有人要那个?

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

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

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


2
您将如何保证在JavaScript执行之前已加载所有CSS?你可以吗?或者您的JavaScript是否足够健壮以应对可能未必加载样式的情况。
乔尼奥(Jonnio)2012年

@Jonnio如果您的JS具有依赖项,则应明确显示该依赖项。否则,您将始终遇到罕见的计时问题。ES6模块是实现此目标的好方法,但是也可以使用许多库。
kmkemp

26

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

通常,“在顶部放置样式表,在底部放置脚本”规则的目的是,这是实现最佳渐进式渲染的最佳方法这对用户体验至关重要。

除了其他因素:假设您的测试是有效的,并且您确实产生了与流行的规则相反的结果,那也就不足为奇了。每个网站(使整个内容显示在用户的屏幕上所需的一切)都不同,并且互联网也在不断发展。


1
我很欣赏你在大胆提出的观点,但OP在谈论你时有所不同的顺序发生了什么在上面,既没有在底部。
nnnnnn '02

1
因此,“假设他的测试是有效的”。
skippr'2

21

由于其他原因,我在Javascript之前加入了CSS文件。

如果我的Javascript需要动态调整某些页面元素的大小(对于那些在某些情况下CSS确实是后面的主要情况),则在JS崩溃后加载CSS可能会导致竞争状况,其中元素的尺寸会在CSS样式之前进行调整被应用,因此当样式最终插入时看起来很奇怪。如果我预先加载CSS,则可以保证一切按预期顺序运行,并且最终布局是我想要的样子。


2
这将在某些浏览器上中断一天。我没猜到
jcolebrand

1
jcolebrand:是的,我写这篇文章时认为我喝的咖啡还不够。(回想起来,我想重要的事情只是避免动态加载CSS并在需要动态调整大小的情况下将JS放入domReady事件中)
hugomg 2012年

脚本不应更改任何显示。那是CSS的工作。HTML =内容,CSS =如何显示内容,javascript动态更改内容。同样,js应该仅在DOMContentLoaded被触发(但有一些非常具体的情况)之后(或同时)执行操作。
brunoais 2012年

@brunoais:某些布局只能使用Javascript创建。例如,任何需要动态调整大小的内容都必须通过Javascript来完成,而某些事情(例如大小为100%-20px)则需要Javascript才能在旧版浏览器中进行移植。
hugomg

@missingno在这种情况下,无论如何都只需使用DOMContentLoaded事件。但是我明白你的意思。(愚蠢的IE!)
brunoais 2012年

10

建议在JavaScript之前包含CSS无效吗?

如果您仅将其视为推荐,则不会。但是,如果您将其视为一成不变的规则?,是的,这是无效的。

来自https://developer.mozilla.org/zh-CN/docs/Web/Reference/Events/DOMContentLoaded

样式表加载了块脚本执行,因此,如果您有一个<script> after <link rel="stylesheet" ...>,页面将无法完成解析-并且DOMContentLoaded将不会触发-在样式表加载之前。

看来您需要了解每个脚本所依赖的内容,并确保脚本的执行被延迟到正确的完成事件之后。如果脚本仅依赖DOM,则可以在ondomready / domcontentloaded中恢复,如果脚本依赖于要加载的图像或要应用的样式表,则如果我正确地阅读了以上引用,则必须将该代码推迟到onload事件之前。

我不认为一种袜子尺寸能适合所有人,尽管那是他们出售的方式,而且我知道一种鞋号不能完全适合所有人。我认为没有一个明确的答案可以首先加载样式或脚本。还要根据具体情况来决定必须以什么顺序加载什么内容,以及什么可以推迟到以后才发布,因为它们不在“关键路径”上。

与评论员交谈,观察者最好将用户的交互能力延迟到表格漂亮为止。你们当中有很多人,而让与您相反的人感到烦恼。他们来到一个站点来实现目标,并且在等待无关紧要的事情来完成加载时,与站点交互的能力的延迟非常令人沮丧。我并不是说您错了,只是您应该知道,存在另一个不具有优先权的派系。

这个问题尤其适用于放置在网站上的所有广告。如果网站作者仅呈现广告内容的占位符div,并确保在将广告注入onload事件之前确保其网站已加载且具有交互性,我会喜欢它。即便如此,我还是希望连续而不是一次加载所有广告,因为它们会影响我在加载肿的广告时甚至滚动网站内容的能力。但这只是一个人的观点。

  • 了解您的用户及其价值。
  • 了解您的用户以及他们使用的浏览环境。
  • 了解每个文件的功能以及先决条件。使一切正常运行将优先于速度和美观。
  • 在开发时,使用显示网络时间轴的工具。
  • 在用户使用的每种环境中进行测试。可能需要根据用户环境动态​​地(在服务器端,在创建页面时)更改加载顺序。
  • 如有疑问,请更改顺序并再次测量。
  • 加载顺序中的混合样式和脚本可能是最佳的。不是所有的一个,而是所有的另一个。
  • 不仅要尝试按什么顺序加载文件,还要尝试在哪里进行实验。头?在体内?后身体?DOM准备/已加载?装了吗
  • 在适当时考虑使用异步和延迟选项,以减少用户在能够与页面进行交互之前所经历的净延迟。测试以确定它们是帮助还是伤害。
  • 在评估最佳负载顺序时,总会有折衷考虑。漂亮与响应式合二为一。

1
链接的文章不再声明“样式表加载了块脚本执行”。那不再是真的吗?
格雷格

@Greg-仍然如此。脚本需要能够查询DOM .style属性,因此样式表仍会阻止脚本执行。如果很聪明,它们可能不会阻止脚本加载,但会阻止script.onLoad事件。
吉米·布雷克-麦凯

10

更新于2017-12-16

我不确定OP中的测试。我决定尝试一下,最终打破了一些神话。

同步<script src...>将阻止下载其下面的资源,直到下载并执行

这不再是真的。看看Chrome 63产生的瀑布:

<head>
<script src="//alias-0.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=1"></script>
<script src="//alias-1.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=2"></script>
<script src="//alias-2.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=3"></script>
</head>

铬网检查器->瀑布

<link rel=stylesheet> 不会阻止下载和执行下面的脚本

这是不正确的。样式表不会阻止下载,但是阻止脚本的执行(此处没有什么解释)。查看由Chrome 63生成的性能图表:

<link href="//alias-0.redacted.com/payload.php?type=css&amp;delay=666" rel="stylesheet">
<script src="//alias-1.redacted.com/payload.php?type=js&amp;delay=333&amp;block=1000"></script>

Chrome开发者工具->性能


牢记以上几点,OP中的结果可以解释如下:

CSS优先:

CSS Download  500ms:<------------------------------------------------>
JS Download   400ms:<-------------------------------------->
JS Execution 1000ms:                                                  <-------------------------------------------------------------------------------------------------->
DOM Ready   @1500ms:                                                                                                                                                      

JS First:

JS Download   400ms:<-------------------------------------->
CSS Download  500ms:<------------------------------------------------>
JS Execution 1000ms:                                        <-------------------------------------------------------------------------------------------------->
DOM Ready   @1400ms:                                                                                                                                            

这就是为什么document.write()是有史以来最糟糕的HTMLDOM构想之一。
brunoais 2012年

1
The reason is that the script may want to get coordinates and other style-dependent properties of elements, like in the example above. Naturally, it has to wait for styles to load. javascript.info / ...为什么相同的假设不适用于JS?对我来说没有太大意义,执行JS的顺序并没有说明其用途。
托尔斯滕·舍宁

4

我不确定使用Java脚本时如何测试“渲染”时间。但是考虑一下

您网站上的一页是50k,这不是不合理的。用户位于东海岸,而服务器位于西部。MTU绝对不是10k,所以会有一些来回旅行。可能需要1/2秒才能收到您的页面和样式表。通常(对我而言)(通过jquery插件等)javascript比CSS要多得多。当您的互联网连接在页面中途阻塞时,也发生了什么,但您可以忽略它(它偶尔发生在我身上,我相信CSS会渲染,但我不是100%确信)。

由于css在头,可能会有其他连接来获取它,这意味着它可能可以在页面之前完成。无论如何,在页面输入期间,页面的其余部分都会被占用,而javascript文件(还有更多字节)则页面未设置样式,这会使站点/连接显得很慢。

即使JS解释器拒绝启动,直到CSS完成之后,下载javascript代码所花费的时间也尤其如此,尤其是在远离服务器的情况下,css的时间将使网站看起来不美观。

它是一个小的优化,但这就是它的原因。


1
服务器在美国东海岸。显然,您也没有意识到他们现在使用CDN的事实。
jcolebrand

3

以下是以上所有主要答案的摘要(或稍后在下面列出):

对于现代浏览器,请将CSS放在您喜欢的任何位置。他们会分析您的html文件(他们称为推测性解析),并开始与html解析并行下载css。

对于旧的浏览器,请始终将css放在顶部(如果您不想首先显示一个裸露但交互式的页面)。

对于所有浏览器,将javascript放在页面上尽可能远的位置,因为它将停止html的解析。最好异步下载(即,ajax调用)

对于特定情况,也有一些实验结果,这些结果声称将javascript放在首位(而不是将CSS放在首位的传统观点)可提供更好的性能,但没有给出逻辑推理,并且缺乏关于广泛适用性的验证,因此您可以现在忽略它。

因此,回答这个问题:是的。对于现代浏览器,建议在JS之前包含CSS的建议无效。尽可能将CSS放在任意位置,并尽可能将JS放在最后。


1

史蒂夫·索德斯(Steve Souders)已经给出了明确的答案,但...

我想知道Sam的原始测试和Josh的重复测试是否都存在问题。

这两个测试似乎都是在低等待时间的连接上执行的,而建立TCP连接的成本却很小。

这不确定如何影响测试结果,我不确定,我想看看通过“正常”延迟连接进行测试的瀑布,但是...

下载的第一个文件获取用于html页面的连接,下载的第二个文件应获取新的连接。(刷新早期会更改该动态,但此处未完成)

在较新的浏览器中,第二个TCP连接以推测方式打开,因此减少了连接/消除了连接的开销,在较旧的浏览器中,情况并非如此,第二个连接将具有打开的开销。

我不确定如何/是否影响测试结果。


不遵循,除非您有非常罕见的流水线操作,否则不太可能减少连接设置...同意应在低延迟下重复测试
Sam Saffron

如果您看一下这个瀑布,您会发现Chrome在需要之前以推测方式在第二个连接处打开了webpagetest.org/result/...(IE9也是一样)...我在考虑TCP的正常延迟,而不是低延迟-什么样的?测试完成的环境?
安迪·戴维斯

2
回复:“史蒂夫·索德斯(Steve Souders)已经给出了明确的答案,但...” Web演进的问题是,没有明确的答案。:)有3-4种加载脚本和更改方式。实际正确的语义实际上应该是史蒂夫说的“在同步JavaScript之前放置CSS”,否则人们会归纳为错误,因为它是所有脚本的规则...
hexalys 2013年

是的,但是大多数人只是同步地包含脚本,因此史蒂夫的建议对初学者是有益的。
安迪·戴维斯

1

我认为这并非在所有情况下都是正确的。因为CSS将下载并行但js无法下载。考虑相同的情况,

不用2个css,而要用2或3个css文件,并尝试这些方法,

1)css..css..js 2)css..js..css 3)js..css..css

我确信css..css..js的效果会比其他所有结果更好。


0

我们必须记住,新的浏览器已经在其Javascript引擎,解析器等上工作,从而优化了常见的代码和标记问题,从而使<= IE8之类的古代浏览器所遇到的问题不再与之相关,不仅与不仅考虑标记,还涉及JavaScript变量,元素选择器等的使用。在不久的将来,我可以看到一种情况,即技术已经到了性能不再是真正问题的地步。


性能始终是一个问题。我几乎几乎忽略了存在未遵循规范的浏览器。我只是准备我的代码,以便遵循规范的代码可以全速工作,而其他人则可以使其工作。因此,例如,如果它仅在IE8中可用,就可以了。
brunoais 2012年

-5

就个人而言,我不会过分强调这种“民间智慧”。过去可能是正确的,现在可能不正确。我假设与网页的解释和渲染有关的所有操作都是完全异步的(“获取”和“执行”是两个完全不同的事情,可能由不同的线程处理),并且在任何情况下都完全超出您的控制或关注范围。

我将CSS引用以及对外部脚本的所有引用都放在文档的“ head”部分中。(某些脚本可能需要放置在正文中,如果有,则应强制执行。)

除此之外,如果您观察到“在此浏览器上,这似乎比这快/慢”,请将此观察结果视为有趣但无关紧要的好奇心,并且不要让它影响您的设计决策。太多的事情改变得太快。 (任何人都想押注Firefox团队再发布他们的产品的另一个临时版本之前要花多少分钟?是的,我也不是。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.