浏览器不同的呈现行为,具有不同的脚本位置和链接标记

时间:2015-10-29 19:11:42

标签: javascript html5 css3 dom rendering

我试图了解HTML在浏览器中何时在屏幕上呈现。

我阅读this S.O. 回答并尝试了一些用例,并观察到一些与链接中共享的模型不相符的内容,
我也似乎无法为观察找到一致的思维模型。

适合所讨论案例的浏览器呈现顺序是什么?

案例A: Image-A enter image description here

  1. 当HTML解析器到达M1时,显示M1。
  2. 然后解析器到达脚本标记它等待js文件下载和解析。
  3. 然后解析器到达M3,显示M3。
  4. 案例A与大多数答案中描述的顺序不一致。 Huray!让我们继续前进。

    案例B: Image-B enter image description here

    1. HTML解析器到达M1, M1不显示在CASE A
    2. HTML解析器到达 link 标签,等待css下载和解析。
    3. 显示M1和M2,因此在渲染M1之前等待样式表下载。
    4. 然后解析器到达脚本标记它等待js文件下载和解析。
    5. 然后解析器到达M3,显示M3。
    6. 所以Case-B表明它没有渲染M1,它在渲染之前等待CSS下载。 所以可能渲染器需要在渲染之前知道CSS。

      案例:C 图片C

      enter image description here

      所以从案例B开始,我们假设渲染器可能需要知道CSS 让我们看一下案例C:

      1. HTML解析器到达M1,显示M1。 它不应该显示,因为我们在B情况下看到它应该等待css加载
      2. 现在解析器到达脚本,它等待js下载和解析器。
      3. 显示M2,M3
      4. 修改 建议的思维模型解释了上述行为..(但需要审查/改进)

        1. Script不是渲染器阻止标记
        2. link是一个阻止标记的渲染器
        3. 考虑到渲染器 HTML解析器是两个线程。
        4. HTML解析器可以将内容发送到渲染器进行渲染。
        5. HTML解析器可以将块信号发送到渲染器。阻止渲染器渲染任何至少一次渲染的html。
        6. HTML解析器可以向渲染器发送解锁信号。解除渲染任何未呈现一次的HTML的渲染器。
        7. 通过上述模型,我们可以解释案例B和案例C:
          案例B说明:

          1. HTML解析器到达M1,M1发送到渲染器。
          2. HTML解析器到达链接标记,解析器向渲染器发送阻塞信号。
          3. 渲染器在渲染M1之前,它有一个阻塞信号,因此M1不显示。
          4. HTML解析器完整链接标记解析(下载)并向呈现器发送解除阻塞信号,一旦接收到解锁信号,它就呈现M1。
          5. HTML解析器到达M2,M2发送到渲染器。
          6. HTML解析器到达脚本标记,因为脚本标记不是渲染器阻止标记,渲染器可以自由渲染html。
          7. HTML解析器完成脚本标记的解析(下载)。
          8. HTML解析器到达M3,M3发送到渲染器。
          9. 同样我们可以干运行 CASE C ,它完全适合上述模型。

            我的模特是正确的还是有问题?

1 个答案:

答案 0 :(得分:3)

你几乎是对的。 除了它更简单 - 渲染器是被动的,不接收“阻塞信号”。 在有人要求之前,它不会渲染(更新显示以反映dom树)。

  1. 您的HTML无效 - 您可能无法将<link rel=...>放入正文中。 (生活HTML 4.2.4

  2. 如您所知,样式表是 render-blocking 资源 - 它会阻止内容呈现, 与脚本相反,脚本将暂停并呈现已解析的内容。

  3. 以下是我将如何解释它:

    案例B:M1 - stylesheet - M2 - script - M3

    1. 浏览器获取HTML。 M1进入DOM树。 M1尚未显示,渲染器未被要求工作。
    2. 样式表加载。 (实际上它会阻止M1渲染)
    3. 样式表已完成。 M1仍然显示。 (两个步骤)
    4. M2进入DOM树。 M1和M2尚未显示。
    5. 脚本触发渲染,从而显示M1和M2,然后加载。
    6. 脚本完成。没有什么变化(就像这个案子一样)。
    7. M3进入DOM树,尚未显示。
    8. 完成文档,呈现页面,因此显示M3。
    9.   

      这些行为是故意的。   曾几何时,js很慢,脚本需要很长时间才能运行,   而样式表默认(并且仍然)对于隐藏元素很重要。   时间可能已经改变,但这些行为不太可能改变。

      案例C:M1 - script - M2 - link - M3

      1. 浏览器获取HTML。 M1进入DOM树。 M1尚未显示。
      2. 脚本触发渲染,从而显示M1,然后加载。
      3. 脚本完成。什么都没有改变。
      4. M2进入DOM树。它尚未显示。
      5. 样式表加载,实际上阻止了M2。
      6. 样式表已完成。 M2仍未显示。
      7. M3进入DOM树,尚未显示。
      8. 完成文档,渲染页面,显示M2和M3。
      9.   

        根据线程,实际显示过程为very complicated,在某种意义上,浏览器会显着varies。   例如,DOM为not thread safe。   想想这意味着什么。

             

        为了简单起见,您可以将浏览器处理视为在各个模块之间流动的数据和事件。   以下是一些Firefox渲染子系统:

             

        Diagram showing 10 interlinked modules related to HTML rendering