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. Python3.7安装pyspider

    下面是Python3.7安装pyspider的方式,能安装成功但是后期有很多问题,所以不建议,请使用3.5版本的Python进行安装!!!由于要做爬虫工作,所以学习pyspider框架,下面介绍安装步 ...

  2. Docker 容器相关技术

    Docker 依赖的Linux内核特性 Namespaces 命名空间 Control groups (cgroups) 控制组 理解这两个特性,能够更好的帮助我们理解docker的资源分配和管理 N ...

  3. 洛谷 P1854 花店橱窗布置

    题目描述 某花店现有F束花,每一束花的品种都不一样,同时至少有同样数量的花瓶,被按顺序摆成一行,花瓶的位置是固定的,从左到右按1到V顺序编号,V是花瓶的数目.花束可以移动,并且每束花用1到F的整数标识 ...

  4. GO语言heap剖析及利用heap实现优先级队列

    GO语言heap剖析 本节内容 heap使用 heap提供的方法 heap源码剖析 利用heap实现优先级队列 1. heap使用 在go语言的标准库container中,实现了三中数据类型:heap ...

  5. git统计当前分支提交次数

    切换到您要统计的分支,然后Git Bash here,执行如下代码即可 : git log --author="您的用户名" --since='开始日期' --oneline | ...

  6. Operating System-进程/线程内部通信-管程(Monitor)介绍,实现以及应用

    本文主要内容: 管程(Monitor)介绍 管程实现 管程应用 一.管程(Monitor)介绍 1.1 管程 前一篇文章介绍了信号量以及使用,信号量已经提供了一个方便且高效的进程同步机制,但是信号量有 ...

  7. BZOJ3624:[APIO2008]免费道路

    浅谈并查集:https://www.cnblogs.com/AKMer/p/10360090.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem. ...

  8. Python collections系列之有序字典

    有序字典(orderedDict ) orderdDict是对字典类型的补充,他记住了字典元素添加的顺序 1.创建一个有序字典 import collections dic = collections ...

  9. spark 算子分析

    别的不说先上官网: action 这些算子中需要注意: 1.reduce 和 reduceByKey 虽说都有reduce,但是一个是action级别,一个是transformation级别,速度上会 ...

  10. 非常不错的LTE架构讲解

    <LTE系统协议架构---通俗易懂超经典> <3GPP协议导读> <3GPP协议36211-850中文翻译> <LTE全套协议汇总> <NB-IO ...