FirstPaint
JS阻止冒泡:event.stopPropagation(),一个事实,Parse HTML和evaluate script不会互相阻塞。
1.问题一:页面基本渲染流程是什么样的?
当我们在浏览器输入一个域名后接下来执行哪些流程?可以看一下下面这张图来加强理解:
挑几个重点的(看得懂英文单词)进行解释,1.DNS查询,获取表示该资源的域名所在机器的IP地址;2.SSL阶段,如果走的是HTTPS协议的话,那么就需要验证HTTPS证书的有效性,这时会处于SSL阶段;3.Request Send阶段,此时浏览器会发起Request Send事件;4.TTFB阶段,TTFB的全称叫做Time To First Byte,是指当浏览器发起请求后开始收到第一个字节的等待时间,TTFB反映出了服务端对请求的响应能力,对于TTFB可以这样打个比方加强理解:A向B问了一个问题,B思考了3S之后,开始回答给A听,这里的3S就相当于TTFB时间。5.Content Download阶段,很显然就是字面意思上面所说的那样,就是响应数据的下载时间。
当浏览器接收到请求数据后,会触发receive response,然后在触发receive data事件,接着触发finish loading事件。当触发finish loading之后,如果是HTML文档的话,那么接着执行Parse HTML事件,对于HTML文档来说,通常还会有一些外部资源比如css文档和js脚本文件,那么此时又重复之前的步骤,send request , receive response , receive data , 如果是接收到的文件是css文件的话,那么是在触发receive data事件之后便开始执行Parse Stylesheet阶段,在Parse Stylesheet阶段完成后,才会触发finish loading事件。
如果接收到的文件是js文件的话,那么接下来和HTML一样,receive response -> receive data -> finish loading -> evaluate script。
2.问题三:DOMContentLoaded和onLoad事件分别在什么时机被触发?
DOMContentLoaded事件一般在parse HTML过程完成后被触发(解析到了HTML文档的末尾)。onLoad一般需要等到外部资源也已经加载完成了的时候触发。
3: DOMContentLoaded和onload事件一般是谁写被触发?
正常生产情况大部分都是DOMContentLoaded事件先被触发。但是也不一定,当浏览器finish loading HTML文档后,接着会开始parse HTML,但是呢,parse HTML并不是直接就到HTML文档结尾的,而是分阶段的:先parse HTML到然后停止,然后在继续从终止的地方继续parse HTML到末尾。前面也提到了DOMContentLoaded事件是parse html到了末尾才会可能被触发,如果解析到body都还没有发现外部引用资源的话,那么自然就是先触发onload事件,接着触发DOMContentLoaded事件。
3-1:DOMContentLoaded和onload事件,谁先被触发,谁的callback就先被执行吗?
Chrome下测试结果,哪怕先触发onload事件,DOMContentLoaded的回调方法也一定会先比onload事件的回调方法更早执行。
4.问题四:内嵌css和外部css的流程有什么区别?
对于内嵌CSS(写在页面HTML文件中的style标签内)来说,浏览器自然不会发起send request,receive response,receive data,finish loading这几个事件的,那么问题来了,会触发parse stylesheet事件吗?答案是不会的,而这就是内嵌CSS和外部CSS资源的区别之一。对于内嵌css来说,相关的事件有可能就只是recalculate style了。
7.问题七:对于浏览器来说,哪些关键过程是单线程,哪些是多线程的?
浏览器中的js解释器引擎是单线程的,浏览器内核本身是多线程的,每个页面通常都是由下面几个线程组成的:
- 1.GUI渲染线程
- 2.js引擎线程
- 3.事件触发线程
- 4.异步HTTP线程
- 5.EventLoop轮询的处理线程
8:写在head里面的css link是否会阻塞Parse html过程?
本质:如果script阻塞页面的parse HTML的话,并且head里面有link标签的话,那么evaluate script就会在parse stylesheet之后。那么那些行为下的script会阻塞页面的parse HTML过程呢?head中的script,body中的script。但是需要注意的是,尽管在没有css的情况下,body中的inline script不会阻塞parse HTML过程,但是呢只要存在样式设置的话(inline style或者link),那么此时会阻塞parse HTML过程,evaluate script会在parse stylesheet之后。同时,如果head中的inline script所出现的位置在link的后面的话,那么此时也会阻塞parse HTML过程,并且evaluate script会在parse stylesheet之后。
8-1:在没有script的情况下,写在body里面css link会阻塞parse HTML吗?
**会的,在没有script的情况下,写在body里面的css link会阻塞parse HTML过程,在说清楚一些,只是资源的网络加载过程阻塞了parse HTML的过程,当这些样式link的finish loading被触发之后的parse stylesheet是不会阻塞parse HTML的,两个工作流程之间并不会相互阻塞。同时parse HTML和recalculate style之间也是不会相互阻塞的。值得一提的是,如果有多个外部样式link的话,那么并不是每触发某个link的finish loading之后便会立马触发parse stylesheet过程。
8-2:总结,对于下面的代码,考虑阻塞parse HTML的情况:
1 |
|
Chrome下情况大致如下:
测试场景 | 是否阻塞parse HTML | onload,DOMContentLoaded,First Paint谁先被触发 | 首先被触发的事件的触发时间 | FirstPaint被触发时间 |
---|---|---|---|---|
没有js,head中写style标签 | 不阻塞 | onload > DOMContentLoaded > FirstPaint | ~94ms | ~105ms |
没有js,head中写link | 不阻塞 | DOMContentLoaded > onload > FirstPaint | ~86ms | ~764ms |
没有js,body中写style | 不阻塞 | onload > DOMContentLoaded > FirstPaint | ~59ms | ~81ms |
没有js,body中写link | 阻塞 | DOMContentLoaded > FirstPaint > onload | ~524ms | ~616ms |
没有css,head中写inline script | 不阻塞 | onload > DOMContentLoaded > FirstPaint | ~59ms | ~85ms |
没有css,head中写script | 阻塞 | onload > DOMContentLoaded > FirstPaint | ~356ms | ~366ms |
没有css,body里面写inline script | 不阻塞 | onload > DOMContentLoaded > FirstPaint | ~85ms | ~91ms |
没有css,body里面写script | 阻塞 | onload > DOMContentLoaded > FirstPaint | ~361ms | ~365ms |
head中写style标签和inline script | 不阻塞 | onload > DOMContentLoaded > FirstPaint | ~81ms | ~109ms |
head中写style标签和script | 阻塞 | onload > DOMContentLoaded > FirstPaint | ~921ms | ~927ms |
head中写link标签和inline script | 不阻塞 | DOMContentLoaded > onload > FirstPaint | ~88ms | ~394ms |
head中写link标签和script | 阻塞 | evaluate script 一定是会在 所link的css资源的parse stylesheet之后 | ~393ms | ~399ms |
body中写style标签和inline script | 不阻塞 | onload > DOMContentLoaded > FirstPaint | ~73ms | ~111ms |
body中写style标签和script标签 | 阻塞 | DOMContentLoaded > onload > FirstPaint | ~357ms | ~353ms |
body中写link标签和inline script | 阻塞 | DOMContentLoaded > onload > FirstPaint | ~395ms | ~400ms |
body中写link标签和script标签 | 阻塞 | DOMContentLoaded > onload > FirstPaint | ~425ms | ~431ms |
head中写link,body中script | 阻塞 | evaluate script 一定是会在 所link的css资源的parse stylesheet之后 | 未记录 | 未记录 |
head中写style,body中script | 阻塞 | recaluate style 通常会在 evaluate script之前 | 未记录 | 未记录 |
head中写link,body中inline script | evaluate script 会被link的css资源给阻塞 | 未记录 | 未记录 | |
head中写style,body中inline script | 不阻塞 | onload > DOMContentLoaded > FirstPaint | 未记录 | 未记录 |
问:为什么外部资源script不推荐写在head标签里面?
默认的(不加async或者defer),那么不仅网络加载过程会阻塞parse HTML过程,而且当script资源的finish loading事件被触发后,其evaluate script过程也会阻塞parse HTML过程。
10.问题10:parse html和parse stylesheet在浏览器中可以并发执行吗?
可以的,他们之间不会互相阻塞。evaluate script也可以不阻塞parse stylesheet。