浏览器打开一个页面的完整流程(整理)

1. 各个步骤概览

浏览器打开一个页面的完整流程(整理)_第1张图片
参考:
《前端性能监控:window.performance》

2. 页面加载和渲染过程

浏览器打开一个页面的完整流程(整理)_第2张图片
参考:
《web页面加载、解析、渲染过程》

3. 渲染引擎简介

参考:
《浏览器渲染原理及流程》
《DOMContentLoaded与load的区别》
《你不知道的 DOMContentLoaded》
《浏览器渲染过程》

区分DOMContentLoaded事件和load事件

  • DOMContentLoaded事件:
    The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.
    对应$(document).ready(function() { // …代码… });
  • load事件:
    The onload property of the GlobalEventHandlers mixin is an EventHandler that processes load events on a Window, XMLHttpRequest, element, etc.
    对应$(document).load(function() { // …代码… });

所以:

  1. 如果只是想操作dom元素,那么在ready函数里就可以进行了;
  2. DOMContentLoaded事件标志着:html中的css都下载完了,js都下载和执行完了;但是并不保证页面已经被完整渲染。

这里引出一个问题:
我们为什么一再强调将css放在头部,将js文件放在尾部?
常见的回答是:因为浏览器生成Dom树的时候是一行一行读HTML代码的,script标签放在最后面就不会影响前面的页面的渲染。
那么问题来了,既然Dom树完全生成好后页面才能渲染出来,浏览器又必须读完全部HTML才能生成完整的Dom树,script标签不放在body底部是不是也一样,因为dom树的生成需要整个文档解析完毕。

First Paint(首次有效绘制)与DOMContentLoaded事件的关系

浏览器确实是必须读完全部HTML才能生成完整的Dom树,但是浏览器并不是等到有了一个完整的Dom树才进行渲染。Dom树是深度优先生成的,也可以说是从上往下一个节点一个节点的生成的。一旦有节点生成,浏览器就会尝试着去渲染页面。第一次渲染成功的时间就是First Paint(首次有效绘制)时间。

这里回答上面的问题:
“将css放在头部,将js文件放在尾部”是为了尽可能的提前First Paint,减少用户的白屏等待时间。(白屏等待时间=First Paint时间-用户在浏览器中输入网址的时间)
“将css放在头部,将js文件放在尾部”并不能提前DOMContentLoaded事件,无论js文件放在哪里,DOMContentLoaded事件都会等所有的js(除了async,见下小节)执行完成之后才会触发。

defer和async区别,以及对DOMContentLoaded事件的影响

  • 同步脚本:
    立刻下载、立刻执行,下载和执行的过程都会阻塞对html文档的解析

  • defer脚本:
    立刻下载、等html解析结束之后再执行,下载过程是异步的,执行时html文档以及解析完了,所以不会阻塞对html的解析

  • async脚本:
    立刻下载、立刻执行,下载过程是异步的,执行的过程都会阻塞对html文档的解析

需要注意的是:
defer的本意是推迟,也就是说defer脚本仍然属于html的一部分,只有当所有的defer脚本都执行完了之后才会触发DOMContentLoaded事件;
async的本意是异步,也就是说async脚本已经不属于html了,所以html解析完成了就会立刻触发DOMContentLoaded事件,不管还有没有async脚本在下载或未执行。

那,既然async脚本是异步的,为什么执行的时候还是会阻塞对html文档的解析呢?
答:GUI渲染线程与JS引擎线程是互斥的,因为JS引擎线程在执行过程中可能会发生重绘和回流,所以GUI渲染线程执行时候,JS引擎线程会被挂起,等待GUI渲染线程执行完毕才会执行;JS引擎线程执行时候同理。

所以,如果html中有async脚本的话,那DOMContentLoaded事件触发的时间会受到async脚本执行时机的影响,如果async脚本在html解析完成之前执行就会使DOMContentLoaded事件触发推迟。

4. js引擎简介

  • 语法分析
  • 预编译阶段
  • 执行阶段

参考;
《js引擎的执行过程》

你可能感兴趣的:(前端)