The major web browsers load web pages in basically the same way. This process is known as parsing and is described by the HTML5 specification. A high-level understanding of this process is critical to writing web pages that load efficiently.

Parsing overview

As chunks of the HTML source become available from the network (or cache, filesystem, etc), they are streamed to the HTML parser. Next, in a process known as tokenization, the parser iterates through the source generating a token for (most notably) each start tag, end tag and character outside of a tag.

For example the input source <b>hello</b> yields 7 tokens:

start-tag { name: b }
character { data: h }
character { data: e }
character { data: l }
character { data: l }
character { data: o }
end-tag { name: b }

After each token is generated it is serially passed to the next major subsystem: the tree builder. The tree builder dynamically modifies the Document's DOM tree to reflect the new token.

The 7 input tokens above yield the following DOM tree:

<html>
<head>
<body>
<b>
"hello"

Fetching subresources

A frequent operation performed by the tree builder is creating a new HTML element and inserting it into the Document. It is at the point of insertion that HTML elements which load subresources begin fetching the subresource.

Running scripts

This parsing algorithm seems to translate HTML source into a DOM tree as efficiently as possible. That is, except for one wrinkle: scripts. When the tree builder encounters an end-tag token for a script, it must serially execute the script before parsing can continue (unless the associated script start-tag has the defer or async attribute).

There are two significant preconditions which must be fulfilled before a script can execute:

  1. If the script is external its source must be fully downloaded.
  2. For any script, all stylesheets in the document must be fully downloaded.

This means often the parser must idly wait while scripts and stylesheets are downloaded.

Why must parsing halt?

Well, a script may document.write something which affects further parsing or it may query something about the DOM which would yield incorrect results if parsing had continued (for instance the number of image elements in the DOM).

Why wait for stylesheets?

A script may expect to access the CSSOM directly or it may query an attribute of a DOM node which depends on the stylesheet (for example, how wide is a certain <table>).

Is it inefficient to block parsing?

Yes. Subresource download times often have a large constant factor limited by round trip time. This means it is faster to download two resources in parallel than to download the same two in serial. More obviously, the browser is also free to do CPU work while waiting on the network. For these reasons it is critical to efficient loading of a web page that subresource fetches are initiated as soon as possible. When parsing is blocked, the tree builder is not able to insert subsequent elements into the DOM, and thus subsequent subresource downloads are not initiated even if the HTML source which includes them is already available to the parser.

Mitigating blocking

As I've blogged previously, when the parser becomes blocked WebKit will run a lightweight parser known as the preload scanner. It mitigates the blocking problem by scanning ahead and fetching certain subresource that may be required. Other browsers employ similar techniques.

It is important to note that even with preload scanning, parsing is still blocked. Nodes cannot be added to the DOM tree. Although I haven't covered how a DOM tree becomes a render tree, layout or painting, it should be obvious that before a node is in the DOM tree it cannot be painted to the screen.

Finishing parsing

After the entire source has been parsed, first all deferred scripts will be executed (waiting for their source and all pending stylesheets to download). Their completion triggers the DOMContentLoaded event to be fired. Next, the parser will wait for any pending async scripts to finish loading and executing. Finally, once all subresources have finished downloading, the window's load event will be fired and parsing is complete.

Takeaway

With this understanding, it becomes clear how important it is to carefully consider where and how stylesheets and scripts are included in the document. Those decisions can have a significant impact on the efficiency of the page load.

How a web page loads的更多相关文章

  1. [转]How WebKit Loads a Web Page

    ref:https://www.webkit.org/blog/1188/how-webkit-loads-a-web-page/ Before WebKit can render a web pag ...

  2. 解读Web Page Diagnostics网页细分图

    解读Web Page Diagnostics网页细分图 http://blog.sina.com.cn/s/blog_62b8fc330100red5.html Web Page Diagnostic ...

  3. 网页细分图结果分析(Web Page Diagnostics)

    Discuz开源论坛网页细分图结果分析(Web Page Diagnostics) 续LR实战之Discuz开源论坛项目,之前一直是创建虚拟用户脚本(Virtual User Generator)和场 ...

  4. Atitit.web三大编程模型 Web Page Web Forms 和 MVC

    Atitit.web三大编程模型 Web Page    Web Forms 和 MVC 1. 编程模型是 Web Forms 和 MVC (Model, View, Controller). 2.  ...

  5. [转]Calling Web Service Functions Asynchronously from a Web Page 异步调用WebServices

    本文转自:http://www.codeproject.com/Articles/70441/Calling-Web-Service-Functions-Asynchronously-from Ove ...

  6. Tutorial: Importing and analyzing data from a Web Page using Power BI Desktop

    In this tutorial, you will learn how to import a table of data from a Web page and create a report t ...

  7. Android WebView常见问题的解决方案总结----例如Web page not available

    之前android虚拟机一直都可以直接联网,今天写了一个WebView之后,突然报出了Web page not available的错误,但是查看虚拟机自带的浏览器,是可以上网的,所以检查还是代码的问 ...

  8. LR实战之Discuz开源论坛——网页细分图结果分析(Web Page Diagnostics)

    续LR实战之Discuz开源论坛项目,之前一直是创建虚拟用户脚本(Virtual User Generator)和场景(Controller),现在,终于到了LoadRunner性能测试结果分析(An ...

  9. Home | eMine: Web Page Transcoding Based on Eye Tracking Project Page

    Home | eMine: Web Page Transcoding Based on Eye Tracking Project Page The World Wide Web (web) has m ...

随机推荐

  1. Brackets (区间DP)

    个人心得:今天就做了这些区间DP,这一题开始想用最长子序列那些套路的,后面发现不满足无后效性的问题,即(,)的配对 对结果有一定的影响,后面想着就用上一题的思想就慢慢的从小一步一步递增,后面想着越来越 ...

  2. java代码从键盘输入执行次数,数,然后排序

    总结:实现从键盘控制执行次数,困惑我很久,直到昨日在提问时,网友说通过循环是肯定可以的所以顿悟了 package com.c2; import java.util.Arrays; import jav ...

  3. kafka集群安装和kafka-manager

    1.软件环境 (3台服务器-测试)10.11.12.31 mykafka110.11.12.32 mykafka210.11.12.33 mykafka3 [root@localhost ~]# ca ...

  4. WebApi学习系列

      最近有一些时间,打算学习和整理一下Web API的一些学习资料的翻译工作.以下是对Web API 的大概目录的整理.欢迎更多的朋友一起加入到学习Web API 的队伍中来,如果你想贡献自己的,请联 ...

  5. 发任务找不到test-unit报错

    发任务的时候因找不到gem包test-unit报错, 出错行: require 'test/unit' require 'test/unit/testresult' 解决办法如下 1.通过命令查看ge ...

  6. json 工具处理类

    package com.js.ai.modules.pointwall.util; import java.lang.reflect.Type; import java.net.URLDecoder; ...

  7. 2016.5.30实现透明Panel及控件置顶的方法

    想放置一个透明Panel在某控件上端,实现效果是可透过此Panel看见下面控件,但鼠标点击却无任何反应. 1.新建置自定义Panel类 using System; using System.Colle ...

  8. spring MVC 异常处理整理

    一.异常结构 1.异常由外到内如下: web服务器处理异常--->web应用里面web.xml处理异常--->Spring框架处理异常---->控制器注释处理异常--->控制器 ...

  9. JavaScript中给对象添加方法

    在JavaScript中,我们经常要给已定义的对象添加一些方法,如下:    function circle(w,h){      this.width=w;      this.height=h; ...

  10. ABP模块配置

    介绍 我们知道ABP中模块的配置都是通过模块的Configuration属性来设置的.例如在模块的生命周期方法中可以进行一系列的配置 审计 MQ Redis....也可以替换一些ABP默认配置 通常我 ...