浏览器的工作原理

1. 影响浏览器渲染方式的文档模式

每个浏览器都有自己的页面渲染引擎。渲染引擎包括两部分:一部分负责 HTML、CSS 代码的解析(渲染引擎,如 blink 引擎 or 内核),一部分负责 JavaScript 代码的解析(JavaScript 引擎,如 V8 引擎)。浏览器的渲染模式(以何种文档模式进行渲染)主要对 CSS 解析有影响(也对脚本有一些影响)。不同的渲染模式,在 CSS 解析上存在差异,比如对盒模型的处理。
不同的渲染模式是历史遗留问题造成的。早期 W3C 没统一标准,浏览器生产商自己决定页面如何渲染;标准出来后,现有浏览器渲染肯定存在与标准不同的地方。为了兼容,就出现了两种浏览器渲染模式(IE 最早提出),正统叫法为文档模式(Document Mode)(如果文档是按照标准编写的,浏览器采用标准渲染模式;如果文档并没有按照标准编写,那么浏览器以怪异模式渲染)。此外,还有第三种模式—近标准模式。那么浏览器又该如何知道文档有没有按照标准编写呢?实际上浏览器在渲染页面之前会检查两个内容,一个是页面是否有 DOCTYPE 信息,另外一个是页面是否有 x-ua-compatible 信息。DOCTYPE 告诉浏览器:我的文档是哪种模式,你确定后,就按这种模式渲染;如果没有这个头信息,浏览器就按怪异模式渲染。x-ua-compatible 是 IE8 的一个专有<meta>属性,可以指定浏览器以怎样的模式进行渲染。
注意:浏览器模式和浏览器渲染模式是两个概念,前者可以理解为IE浏览器中特有的概念,后者在本文中就是指文档模式。

2. HTML 文档的解析过程

当用户在浏览器键入某网站地址,网站首页文档 index.html 加载完成后,浏览器开始解析 HTML。下文根据不同的 HTML 资源结构分析解析过程。

2.1 纯 HTML 文档,无 CSS 和脚本

如果 HTML 文档中只有 HTML,没有 CSS 和脚本的话,问题极其简单。浏览器解析 HTML,构建 DOM 树,DOM 树构建完成后(触发 DOMContentLoaded 事件),构建 render 树,接着布局和绘制像素。

2.2 包含内联样式和内联脚本的 HTML 文档

如果 HTML 文档中存在内联样式和脚本,这个时候,问题变得稍微复杂一些。浏览器解析 HTML,构建 DOM 树,当解析到<style>标签时,样式信息开始被解析,CSSOM 被构建,但是它并不会影响到 HTML 的解析和 DOM 树的构建。当 HTML 解析到<script>标签时,因为脚本有可能改变 DOM 内容,所以 HTML 的解析必须等到脚本执行完毕后再继续。脚本又有可能操作 CSSOM ,所以脚本必须等到 CSS 解析完毕后才能执行。确保此刻 CSS 解析完成,脚本被交到 JS 引擎手里,由 JS 引擎执行。当脚本执行完毕,HTML 继续解析,直到全部 HTML 解析完毕,DOM 树构建完成(触发 DOMContentLoaded 事件)。
注意:DOMContentLoaded 事件只和 HTML 的加载和解析有关,一旦 HTML 解析完成,这个事件就会被触发,不管此时还有没有CSS的解析、图片的下载或者异步脚本的加载和执行。DOM 树一旦构建完成,就会开始构建 render 树,并不管 CSS 是否解析完毕。如果构建 render 树的时候,CSS 还没有解析完成,那么 render 树会用占位符代替应该有的 CSSOM 节点,当该节点加载解析好后,再重新计算样式。
但是同步脚本的执行会阻塞 HTML 的解析,从而会影响到 DOMContentLoaded 事件的触发。同时又要注意,CSS 会阻塞 JS 脚本的执行,从而间接影响到 HTML 的解析和 DOMContentLoaded 事件的触发。

2.3 包含外部 CSS 和脚本的 HTML 文档

如果 HTML 文档中存在外联样式表和脚本,问题变得更复杂一点。HTML 文档加载完成后,浏览器首先扫描 HTML 文档,查看有哪些外部资源需要启动 network operation 来请求资源,并在 HTML 解析的同时,发送所有的请求。CSS 资源加载完毕后,会立即开始解析构建 CSSOM。(同步脚本加载完毕后,并不能立刻执行。)当 HTML 解析到<script>标签,先确认脚本加载完毕了没,如果没,那得等;如果加载好了,还得看 CSS 解析好了没。如果没,那还得等;如果 CSS 解析好了,那就能把脚本交给 JS 引擎去执行了。当 JS 执行完毕,HTML 继续解析,DOM 继续构建,直到全部构建完成,DOMContentLoaded 事件被触发。紧接着,就是构建 render 树。
如果脚本有async属性,问题就又不一样了。async属性默认该脚本不会影响到 DOM 内容,所以只要脚本下载完成,(相关)CSS 解析完毕,脚本立刻执行,不用等着 HTML 解析到<script>标签再开始执行。同样,HTML 也不会等着脚本执行完毕再解析。仿佛两者看不到对方,只管做自己的事情就行了。

3. JS 解释器的工作原理

上文提到浏览器在解析 HTML 文档的时候,会把脚本交给 JS 引擎执行,那么 JS 引擎是如何执行脚本(evaluating script)的呢?

3.1 扫描全局变量,确定所有已声明的变量或函数名

你如果利用 chrome 控制台调试 JS 代码,这个过程是看不到的,但确实存在。JS 解释器对脚本进行全局扫描,结束后得到全局环境中的变量对象,此过程发生了变量声明提升和函数声明提升。所有变量都没被赋值,其值为 undefined;函数声明提升还包括了函数体的提升。下图是个例子:

全局环境中的变量对象

备注:你可能会好奇上面这个图是怎么回事,这里简要概述一下:黄色区块表示JS执行环境,白色表格代表变量对象键值对模型,表格左列为全局变量(变量对象中的key),说明当前全局环境中共有modeloctopuscatViewcatListView四个变量。
以后会专门写一篇文章介绍JS执行时的内存模型,帮助大家形象理解JS代码的运行机制,从而有助于理解作用域、执行环境、this指向、闭包、继承、原型链等抽象概念。

3.2 顺序执行所有语句

当 JS 解释器知道整个文件中都有哪些声明好的全局变量或函数后,就会开始顺序执行文件中的语句,当然是从第一行开始。如果是赋值语句,就执行赋值操作;如果是函数调用语句,就执行函数调用。
下图是 debugger 刚开始时变量的情况,很明显,刚刚被 JS 解释器点过名,还没有开始执行赋值操作。

变量声明提升

当解释器移动到下一行代码时,这个变量也就被赋值,存储了数据。在本例中这个数据是个对象类型,有两个属性,其中一个是数组,另一个是空值。

变量赋值操作

脚本的最后是函数调用语句:

函数调用

JS 解析器执行到这里,准备调用 octopusinit方法。
当所有的语句执行完毕后,JS 解释器任务结束,主导权交到 HTML 解析器手中,浏览器继续解析 HTML 文档。
从上述过程,我们能看出浏览器解析渲染 HTML 文档是单线程的,除了发送外部资源请求的操作。

4. 总结

浏览器的工作原理是网站性能优化的基础知识。CSS 不会阻塞 HTML 的解析,但是会阻塞渲染,CSS 的解析会阻塞脚本的执行,而脚本会阻塞 HTML 的解析。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容