浏览器渲染页面的原理

145 阅读2分钟

1. 浏览器渲染页面的原理

html文件:字节 -> 字符 -> token -> 节点对象 -> DOM

css文件:字节 -> 字符 -> token -> 节点对象 -> CSSOM

DOM+CSSOM=渲染树

根据渲染树进行布局

  1. 浏览器发送请求以后,服务器返回html文件,第一步开始解析html文件,并且构建dom
    • 在解析html文件的时候遇到link标签,浏览器就去请求css文件,
    • 请求css文件的过程同时也继续解析html文件
  2. 若解析html文件遇到script标签,浏览器就去请求js文件,服务器就会陆续返回css和js文件
    • 遇到js文件时,html会暂停解析,等js执行完成后html再继续解析
    • 如果先返回并解析完成js文件,也是会发生阻塞,不能先执行js文件,必须等CSSOM构建完成了才执行js文件
  3. 接下来就解析css文件,并且构建CSSOM树,此时浏览器依然可以去下载并且解析JS文件
  4. 等CSSOM构建完成以后,就去执行js里的内容了
  5. js执行完成后,构建DOM后,形成渲染树
  6. 然后进行布局
  7. 最后绘制

dom树渲染过程.png

2. 在解析过程中遇到 JavaScript 脚本,如何规避阻塞

script 标签不阻塞页面的方法:

<script> 标签没有 src 特性,那么 asyncdefer特性会被忽略。

  • defer特性:
    • 具有 defer 特性的脚本总是要等到 DOM 解析完毕,但在 DOMContentLoaded 事件之前执行。
    • 具有 defer 特性的多个js脚本并行下载(下载没有顺序),文档顺序执行
    • defer 用于需要整个 DOM 的脚本,脚本的相对执行顺序很重要的时候。
  • async特性:
    • async 异步脚本以“加载优先”的顺序执行。
    • DOMContentLoaded 可能在 async 之前或之后触发,不能保证谁先谁后。
    • async 用于独立脚本,例如计数器或广告,这些脚本的相对执行顺序无关紧要。
  • 动态添加脚本:
    • 默认情况下,动态脚本的行为是“异步”的
    • 先加载完成的脚本先执行(“加载优先”顺序)
      let script = document.createElement('script');
      script.src = "/article/script-async-defer/long.js";
      document.body.append(script); // (*)
      

参考:

  1. 浏览器渲染页面的流程