javascript - ease - trigger css




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

在网上的无数地方,我已经看到了在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 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和Internet Explorer中的结果类似。 然而,在Opera中,排序并不重要。

看起来正在发生的事情是JavaScript解释器拒绝启动,直到下载所有的CSS。 所以,当JavaScript线程获得更多运行时间时,似乎首先使JavaScript包含效率更高。

我是否缺少一些东西,建议放置CSS包括之前的JavaScript包含不正确的东西?

很明显,我们可以添加异步或使用setTimeout来释放渲染线程或将JavaScript代码放入页脚,或者使用JavaScript加载器。 这里的重点是关于头部基本JavaScript位和CSS位的排序。


Personally, I would not place too much emphasis on such "folk wisdom." What may have been true in the past might well not be true now. I would assume that all of the operations relating to a web-page's interpretation and rendering are fully asynchronous ("fetching" something and "acting upon it" are two entirely different things that might be being handled by different threads, etc. ), and in any case entirely beyond your control or your concern.

I'd put CSS references in the "head" portion of the document, along with any references to external scripts. (Some scripts may demand to be placed in the body, and if so, oblige them.)

除此之外......如果你观察到“这看起来比这更快/更慢,在这个/那个浏览器上,”把这个观察看作是一个有趣但不相干的好奇心,不要让它影响你的设计决策。太多事情变化太快。(任何人都希望在Firefox团队发布其产品的另一个临时版本之前多少分钟内下注?Yup,我也没有。)


更新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>

牢记上述内容,OP中的结果可以解释如下:

CSS第一:

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

JS第一:

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

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

  1. 旧版浏览器(Internet Explorer 6-7,Firefox 2等)会在开始下载脚本时阻止所有后续下载。 所以如果你有a.js后跟b.css他们会按顺序下载:先a然后b。 如果你有b.css后跟a.js他们会并行下载,所以页面加载速度更快。

  2. 直到所有样式表下载完成才会呈现 - 在所有浏览器中都是如此。 脚本是不同的 - 它们阻止渲染页面中脚本标记下的所有DOM元素。 如果将脚本放在HEAD中,则意味着整个页面都会被阻止呈现,直到下载了所有样式表和所有脚本。 虽然阻止所有的样式表渲染是非常有意义的(所以你第一次得到正确的样式并且避免未格式化内容FOUC的闪光),但是阻止为整个页面渲染脚本是没有意义的。 通常,脚本不会影响任何DOM元素或DOM元素的一部分。 最好在页面中尽可能低地加载脚本,或者更好地将脚本加载到异步脚本中。

Cuzillion创造例子很有趣。 例如, 此页面在HEAD中有一个脚本,因此整个页面在完成下载之前都是空白的。 但是,如果我们将脚本移动到BODY块的末尾,则页面标题将呈现,因为这些DOM元素出现在SCRIPT标记上方,如您在此页面上所看到的那样。


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

不是,如果你只是把它当作推荐。 但是,如果你把它当作一条坚强而快速的规则呢,是的,它是无效的。

https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded

样式表加载阻止脚本执行,所以如果在<link rel="stylesheet" ...> <script>之后有<script>页面不会完成分析 - 并且DOMContentLoaded不会触发 - 直到加载样式表。

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

我不认为袜子尺寸适合所有人,尽管这是他们销售的方式,我知道一种鞋子尺寸不适合所有人。 我不认为有一个确定的答案来加载首先,样式或脚本。 更重要的是,按照什么样的顺序加载什么以及什么可以推迟到什么时候才能被放在“关键路径”上。

与观察者交谈,他表示最好延迟用户交互的能力,直到表单变得可爱为止。 你们中有很多人在那里,而你们感到相反的是你们。 他们来到一个网站来完成一个目的,并拖延他们与网站互动的能力,同时等待无关紧要的事情来完成加载是非常令人沮丧的。 我并不是说你错了,只是你应该知道存在另一个不同意你的优先权的派别。

这个问题特别适用于所有放在网站上的广告。 如果网站作者仅为广告内容呈现占位符div,并确保在onload事件中注入广告之前已加载并互动网站,我会很喜欢它。 尽管如此,我还是希望看到广告一次性加载,而不是一次性加载,因为它们会影响我在加载臃肿广告的同时滚动网站内容的能力。 但这只是一个人的观点。

  • 了解你的用户和他们的价值。
  • 了解你的用户和他们使用的浏览环境。
  • 知道每个文件的功能,以及它的先决条件是什么。 一切工作都将优先于速度和美观。
  • 使用在开发时向您显示网络时间线的工具。
  • 在用户使用的每个环境中进行测试。 可能需要动态地(服务器端,创建页面时)根据用户环境改变加载顺序。
  • 如有疑问,请改变顺序并再次测量。
  • 加载顺序中的混用风格和脚本可能是最佳的; 不是所有其他人都是。
  • 不仅要试验加载文件的顺序,还要在哪里进行实验。 头? 在身体? 身体后? DOM就绪/加载? 装?
  • 在适当的时候考虑异步并推迟选项,以减少用户在能够与页面交互之前所经历的净延迟。 测试以确定它们是否有帮助或受伤。
  • 评估最佳加载顺序时总会考虑折衷因素。 漂亮与响应只是一个。

我不会过分强调你所得到的结果,我相信这是主观的,但我有理由向你解释,在js之前放置CSS更好。

在加载您的网站时,您会看到两种情况:

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

案例2:白屏>无风格网站>互动>风格网站>风格互动的网站

我真的无法想象任何人选择第二种情况。这意味着使用慢速互联网连接的访问​​者将面临一个没有样式的网站,允许他们使用Javascript进行交互(因为已经加载)。 此外,通过这种方式可以最大限度地缩短查看未打版网站的时间。 为什么会有人想要这样?

它也可以像jQuery那样更好地工作

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

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


我不确定你的测试如何“渲染”你的Java脚本。 不过考虑一下

您网站上的一个页面是50k,这不是不合理的。 用户位于东海岸,而服务器位于西部。 MTU绝对不是10K,所以会有几次来回。 接收您的页面和样式表可能需要1/2秒。 通常(对我来说)javascript(通过jquery插件等)远远超过CSS。 这也是当你的互联网连接在页面中途窒息时发生的事情,但让我们忽略(偶尔发生在我身上,我相信css呈现,但我不是100%确定)。

由于css在头部,可能会有其他连接来获取它,这意味着它可能会在页面完成之前完成。 反正在类型期间页面的其余部分需要和JavaScript文件(这是更多的字节)的页面是无风格的,这使得站点/连接看起来很慢。

即使JS解释器在CSS完成之前拒绝启动,下载javascript代码所用的时间也会缩短,特别是当服务器距离服务器很远的时候,会导致网站看起来不太漂亮。

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


我认为这对所有情况都不会是真的。 因为CSS会下载并行但js不能。 考虑同样的情况,

而不是单一的CSS,拿2或3个CSS文件,并尝试这些方法,

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

我相信css..css..js会比其他所有人都有更好的结果。


由于其他原因,我在JavaScript之前包含CSS文件。

如果我的Javascript需要动态调整一些页面元素的大小(对于那些CSS实际上是主要背景的角落案例),那么在JS出现问题后加载CSS可能会导致竞争状况,其中元素在CSS样式之前调整大小应用程序,因此看起来很奇怪,当样式终于踢了。如果我事先加载CSS,我可以保证东西运行在预定的顺序,最终的布局是我想要的。


这里是上述所有主要答案的摘要 (或者可能在下文中:)

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

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

对于所有浏览器,尽可能将JavaScript放在页面上,因为它会停止解析你的html。 优选地,异步下载(即,ajax调用)

还有一些关于特定情况的实验结果,声称把JavaScript放在第一位(相对于传统的把CSS放在第一位的方式),这样可以提供更好的性能,但没有给出逻辑推理,并且缺乏对广泛适用性的验证,所以你可以现在忽略它。

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





performance