浏览器 / html页面渲染过程

88 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情 >>

浏览器获取到 html 资源后开始解析 html (dom tree) -> 构建 DOM 树

解析到 css 后根据 css 生成 css 规则树 (style rules) -> 产生 CSS 规则树

在 dom 树和 css 规则树都生成完后,

通过 dom 树和 css 规则树生成渲染树( render tree ) -> 构建 render 树

渲染树构建完成后,浏览器开始计算元素的大小和位置( layout ) -> 布局 render 树

根据计算好的节点信息将内容绘制到屏幕上( painting ) -> 绘制 render 树

详细过程

  1. dom 树和 css 规则树的先后顺序

    浏览器获取的 html 资源后自上而下开始解析,生成 dom 树;如果遇到 style 的内联样式和 link 会将 css 交由 css 渲染器构建 css 规则树; 其中加载 link 引入的外部样式文件是异步加载的,并且整个 css 规则树也是与 dom 树的构建是并行的;

  2. Javascript脚本的加载

    由于 js 可以操作 dom,所以在 html 解析到 Javascript 脚本时会停止对 dom 的解析;而 css 的解析会阻塞 js 的执行,所以在某些情况下 css 的解析会导致 dom 的解析;

    script的defer 属性

    • 给 script 标签添加 defer 属性,适用于 js 中涉及到 dom 的操作,或者与其他的 js 有相互引用的关系 添加 defer 属性会将 Javascript 脚本延迟执行,但是 html 解析过程中遇到 script 标签仍然会进行下载
    • defer 脚本会在 dom 解析完成后,DOMContentLoaded事件调用前执行,而且 defer 属性的 js 脚本会按照顺序执行,即在 dom 解析完成后会依次执行 script标签

    script的async属性

    • 给 script 标签添加 async 属性,适用于 js 与 dom 和其他 js 文件无关的情况
    • 添加 defer 属性会将 Javascript 脚本异步执行,html 解析过程中遇到 script 标签会进行下载,且下载完成后立即进行异步执行
    • 由于是异步执行,所以当有多个异步的 js 脚本时无法控制先后执行的顺序,所以有多个异步 js 时,这些 js 不要互相有引用
    • 由于添加 async 属性,使 js 在下载完成后立即执行,所以为了在该 js 中不要进行 dom 的相关操作
  3. 渲染树( render tree )的构建过程

    1. 从 dom 树的根节点开始遍历每一个可见的节点;例如引用 css 文件的 link 标签、引入js 文件的 script 标签和 css 属性设置了 display: none; 的节点
    2. 从 css 规则树 (style rules) 中找到对应的节点,然后根据节点信息和样式组合成渲染树( render tree )