建议在javascript无效之前包含css吗?

Is the recommendation to include CSS before JavaScript invalid?

在网上的无数地方,我都看到了在JavaScript之前包含CSS的建议。一般来说,推理是这样的:

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.

我的实际测试揭示了一些非常不同的事情:

我的测试装具

我使用以下Ruby脚本为各种资源生成特定的延迟:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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。

我使用下面的页面进行测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
  <head>
      test
      <script type='text/javascript'>
          var startTime = new Date();
     
      <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">
  </head>
  <body>
    <p>

      Elapsed time is:
      <script type='text/javascript'>
        document.write(new Date() - startTime);
     
   
</p>    
  </body>
</html>

当我首先包含CSS时,页面需要1.5秒的时间来渲染:

CSS first

当我首先包含javascript时,页面需要1.4秒来呈现:

JavaScript first

我在Chrome、Firefox和Internet Explorer中得到了类似的结果。然而,在歌剧中,点菜并不重要。

似乎发生的是javascript解释器拒绝启动,直到所有的css都被下载。因此,当javascript线程获得更多运行时间时,让javascript包含First似乎更有效。

我是否遗漏了一些内容,建议将css include放在javascript include之前是否不正确?

很明显,我们可以添加async或使用setTimeout释放渲染线程,或将javascript代码放在页脚中,或使用javascript加载程序。这里的要点是关于在头部中对基本的javascript位和css位进行排序。


这是一个非常有趣的问题。我总是把我的CSS 放在我的JS


我不会太强调你得到的结果,我相信这是主观的,但我有理由向你解释,最好在JS之前输入CSS。

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

案例1:白屏>非样式化网站>样式化网站>交互>样式化和交互网站案例2:白屏>非样式化网站>交互>样式化网站>样式化和交互网站我真的无法想象有人会选择第二种情况。这意味着使用慢速互联网连接的访问者将面临一个非样式化的网站,允许他们使用javascript与之交互(因为已经加载了该网站)。此外,通过这种方式,可以最大限度地延长浏览非样式网站的时间。为什么会有人想要?

它在jquery状态下也工作得更好

"When using scripts that rely on the value of CSS style properties,
it's important to reference external stylesheets or embed style
elements before referencing the scripts".

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


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

"在顶部放置样式表和底部脚本"的目的是,一般来说,它是实现最佳渐进渲染的最佳方式,这对于用户体验至关重要。

除此之外,假设你的测试是有效的,而且你真的在产生与流行的规则相反的结果,那就不足为奇了。每一个网站(以及使整个东西出现在用户屏幕上所需的一切)都是不同的,互联网也在不断发展。


我把CSS文件放在javascript之前是因为另一个原因。

如果我的javascript需要动态调整某个页面元素的大小(对于那些在后面CSS确实是主要元素的角情况),那么在JS被腐蚀后加载CSS可能会导致竞争条件,在应用CSS样式之前调整元素的大小,从而在样式最终开始时看起来很奇怪。如果我事先加载CSS,我可以保证事情按预期的顺序运行,并且最终的布局就是我想要的。


建议在javascript无效之前包含css吗?

如果你把它当作一个简单的建议,那就不是了。但如果你把它当作一个硬性的快速规则?,是的,它是无效的。

来自https://developer.mozilla.org/en-us/docs/web/reference/events/domcontentloaded

Stylesheet loads block script execution, so if you have a
after a the page will not finish parsing
- and DOMContentLoaded will not fire - until the stylesheet is loaded.

您似乎需要知道每个脚本依赖什么,并确保脚本的执行延迟到正确的完成事件之后。如果脚本只依赖于dom,它可以在ondomready/domcontentloaded中恢复,如果它依赖于要加载的图像或要应用的样式表,那么如果我正确地读取了上述引用,那么该代码必须延迟到onload事件。

我不认为一个袜子大小适合所有人,即使这是他们的销售方式,我知道一个鞋大小不适合所有人。我不认为有一个明确的答案要先加载样式或脚本。它更多的是一个个案决定什么必须以什么顺序加载,什么可以推迟到以后作为不在"关键路径"上。

与评论说最好延迟用户交互的能力,直到工作表漂亮为止的观察者交谈。你们中的很多人都在外面,你让对方觉得你很讨厌。他们来到一个站点是为了完成一个目标,而他们在等待不重要的事情完成加载的同时,延迟了与一个站点的交互能力,这是非常令人沮丧的。我不是说你错了,只是说你应该意识到存在着另一个派别,而不是你的优先权。

这个问题特别适用于网站上的所有广告。如果网站作者只呈现广告内容的占位符,并确保他们的网站在将广告插入到OnLoad事件之前已加载并交互,我会很高兴的。即便如此,我还是希望看到连续加载的广告而不是一次加载所有的广告,因为它们会影响我在加载膨胀的广告时滚动网站内容的能力。但这只是一个人的观点。

  • 了解您的用户及其价值。
  • 了解您的用户及其使用的浏览环境。
  • 了解每个文件的功能及其先决条件。让一切正常运转将优先于速度和漂亮。
  • 开发时使用显示网络时间线的工具。
  • 在用户使用的每个环境中进行测试。可能需要根据用户环境动态(服务器端,创建页面时)更改加载顺序。
  • 如有疑问,请更改顺序并再次测量。
  • 在加载顺序中混合样式和脚本可能是最佳的;不是所有样式和脚本都是最佳的。
  • 实验不只是加载文件的顺序,而是在哪里。Head?体内?身体之后?DOM准备好了吗?加载?
  • 在适当的时候考虑ASYNC和延迟选项,以减少用户在与页面交互之前体验到的网络延迟。测试以确定它们是否有帮助或伤害。
  • 在评估最佳负荷顺序时,总是要考虑权衡。漂亮与反应灵敏仅为一。


更新2017至12 16

我对OP的测试不太确定。我决定试一下,最后揭穿一些神话。

Synchronous


我们必须记住,新的浏览器已经在他们的javascript引擎、解析器等上进行了工作,优化了常见的代码和标记问题,这样一来,在古代浏览器中遇到的问题(如<=ie8)就不再相关,不仅与标记有关,而且与javascript变量、元素选择器等的使用也无关。我可以看到,在不久的将来,技术已经达到了一个点,性能不再是真正的问题。


就我个人而言,我不会过于强调这种"民间智慧",过去可能是真的,现在可能不是真的。我假设与网页的解释和呈现相关的所有操作都是完全异步的("获取"和"执行"是两个完全不同的东西,可能由不同的线程处理,等等),在任何情况下都完全超出了您的控制或关注范围。

我将把CSS引用和任何对外部脚本的引用放在文档的"head"部分。(有些脚本可能需要放在正文中,如果需要,请强制执行。)

除此之外…如果您观察到"在这个/那个浏览器上,这似乎比那个更快/更慢",请将这个观察视为一个有趣但不相关的好奇心,不要让它影响您的设计决策。太多的事情变化太快。(有人想赌在火狐团队推出他们产品的另一个临时版本之前还有多少分钟?是的,我也是。)