所有我们随意的给一个非常简单的网页,基本构造如下:
然后我们运行在chrome
中打开它,然后调出控制台,选择我们的Timeline
项(它显示会有几种颜色,这里先提一下,蓝色表示HTML
解析,黄色表示会触发或者是运行了javascript
,紫色表示渲染,绿色表示绘制,其实Timeline
项中也对这个进行了说明,希望大家可以学会使用Timeline
去进行一些性能优化的工作),然后就会看到如下图:
然后我们看到第二个窗口的Main
区域,我们在这个区域滚动鼠标的滑轮会让它放大和缩小,然后我们看看网页加载的过程和它在这中间干了些什么。
首先是在网页加载之前会触发beforeunload
事件。
然后就是SendRequest
去获取服务器端的index.html
文件。
然后就是接收到index.html
文件,接着就是触发pagehide
,visibilitychange
,webkitvisibilitychange
,unload
这四个事件,接着就是触发readystatechange
事件,然后浏览器开始读取我们的index.html
文件,读完之后呢,浏览器就开始解析HTML
文件
然后我们发现了,在解析HTML
的过程中,只要有src
和href
这样的请求都会在解析HTML
的过程中发出。图中红框框中的就是我们的script
和link
要求的js
和css
文件,他们都会在解析HTML
的过程中向服务器发送文件的请求。
图中正好就是send request(test1.js)
,send request(test2.js)
,send request(test3.js)
,send request(nodejss.js)
,send request(test4.js)
,这一点我们清楚的事,解析HTML
是自上而下的。
接着就发生了接收到了test1.js
和test2.js
,(Receive Response(test1.js)
,Receive Response(test1.js)
),这里我们要清楚的是,我们发送了请求文件的消息,然后接到了服务器发送过来的文件,和我们解析文件时不冲突的,也就是说我们解析HTML
文件的和接收到文件这个东西是并行的,不冲突的,或者说是这两个一码归一码,解析HTML
的时候是可以接受服务器传送来的文件的。
虽然他们接受文件时不冲突的,但是对于script
而言,如果你没有用defer
或者async
的话,必须知道一件事情,那就是顺序执行和阻塞渲染。看下面的图,你就明白了,当浏览器解析完HTML之后,浏览器就开始进行DOM
节点的构建了,从HTML
头部开始往下构建DOM
节点,当执行到script
卡住,等待我们的script
从服务器送过来,如果送过来了,浏览器就会读取接收到的文件。
当浏览器读取完test1.js
文件后,浏览器是直接编译程序然后运行,而此时浏览器除了可以并行接受之前请求服务器的文件之外就不能做其他事情了,不能接着往下处理,必须等到这一份javascript
代码执行完后才能往下走。当执行完一个script
包裹的javascript
文件后,又会触发load
事件,告诉浏览器执行完了,然后浏览器接着往下处理。
然而又碰到一个Script
又会等待,知道接收到这个文件和上述的处理一样,然后接着往下处理,直到DOM
节点构造完。
等你DOM
节点构造完后,就会触发readystatechange
事件,然后就是调用document.onreadystatechange
,运行完,然后就是触发DOMContentLoaded
,所以我们的onreadystatechange
执行的顺序在DOMContentLoaded
之前,但是此时DOM
节点已经构造完了。
接着就是界面样式重新渲染。
接着又会触发readystatechange
事件和调用document.onreadystatechange
(这也是为什么我们在document.onreadystatechange
写东西的时候,它会运行两遍),这就是触发load
事件,然后调用window.onload
,接着就是触发pageshow
的事件来显示最终的网页。
这就是打开一个网页的全过程。