全面解析:HTML页面的加载全过程(三)--浏览器渲染之HTML解析

107 阅读4分钟

当浏览器的网络线程收到 HTML 文档后,会产生一个渲染任务,并将其传递给渲染主线程的消息队列。

在事件循环机制的作用下,渲染主线程取出消息队列中的渲染任务,开启渲染流程。 在这里插入图片描述

解析HTML

当访问的服务器返回html文件即html代码,浏览器需要解析html代码并进行渲染

“解析”是浏览器将通过网络接收的数据转换为 DOM 和 CSSOM 的步骤,通过渲染器在屏幕上将它们绘制成页面。

构建 DOM 树

HTML 标记包括开始和结束标记,以及属性名和值。

一个 HTML 文件,经过 HTML 解析器解析,最终输出树状结构的 DOM

DOM 是保持在内存中树状结构, 可以通过 JavaScript 来查询和修改内容

在这里插入图片描述

构建 CSSOM 树

(一)理解几个概念,css引入方式:

1、引用外部文件--外部样式表

<link href="css/mystyle.css" rel="stylesheet" />

2、在head标签里面定义--内部样式表

<style type="text/css">
    h1 {
        text-align: center;
    }
</style>

3、直接在标签添加样式--内联样式

<h1 style="text-align:center;">内容</h1>

4、浏览器会存在“用户代理样式表”,即浏览器内置了一套样式表--浏览器默认样式表 在这里插入图片描述

p标签就有浏览器默认的样式

(二)CSSOM树

1、因为浏览器无法解析纯文本的 CSS 样式,当渲染引擎接收到CSS文本时, 会将 CSS 文本转换为浏览器可以理解的结构 StyleSheets,即 CSSOM ,并提供了查询和修改功能。

2、CSS----被解析成CSSOM(CSS Object Model),树形结构

3、构建 CSSOM 非常快,在 web 性能优化方面,它是可轻易实现

4、根节点(StyleSheetList)是网页中所有的样式表

5、二级子节点会包含内部样式表外部样式表内联样式表浏览器默认样式表

在这里插入图片描述

6、可在控制台查看style结构 在这里插入图片描述

7、可通过document.styleSheets访问cssom

image.png 用法如:

var cssRule1 = document.styleSheets[0].cssRules[0];
cssRule1.style.fontWeight = "bold";
cssRule1.selectorText = "div";


资源加载

为了提高解析效率,浏览器在开始解析前,会启动一个预解析的线程,率先下载 HTML 中的外部 CSS 文件和 外部的 JS 文件。

1、外部css加载---CSS 不会阻塞 HTML 解析

如主线程解析到<link href='...'>位置,此时外部的 CSS 文件还没有下载解析好,主线程不会等待,继续解析后续的 HTML。

下载和解析 CSS 的工作是在预解析线程中进行的---这就是 CSS 不会阻塞 HTML 解析的原因。 在这里插入图片描述

2、外部js加载---JS 会阻塞 HTML 解析

渲染主线程遇到 JS 的

因为 JS 代码也许会修改 DOM 树,因此必须在继续解析HTML文档前执行JavaScript。

在这里插入图片描述

常见面试题:

1、请解释一下 script标签中的 defer 和 async属性

async:下载过程不阻塞页面渲染,但下载完成后,会停止解析html,转而执行脚本,需要等待脚本执行完,才继续继续html defer:下载过程不阻塞页面渲染,会等待html文档解析完,DOMContentLoaded事件的触发前, 才执行defer脚本。

在这里插入图片描述

  • async

    • 异步加载:浏览器在解析HTML文档的同时并行加载脚本。
    • 立即执行:一旦脚本加载完成,便立即执行,不会等待HTML文档的解析完成。
    • 非顺序执行:多个带有 async 属性的脚本会根据它们加载完成的顺序执行,而不是它们在文档中的顺序。
    • 优先外部脚本:更适合独立的、没有依赖其他脚本或DOM内容的脚本,例如第三方广告、数据收集或分析脚本。
      <script src="script.js" async></script>
      
  • defer:

    • 异步加载:浏览器在解析HTML文档的同时并行加载脚本。
    • 延迟执行:脚本文件会在 HTML 文档完全解析和 DOMContentLoaded事件执行之前执行。
    • 顺序执行:多个带有 defer 属性的脚本会按它们在文档中的出现顺序执行。
    • DOM 依赖:适合需要在完整的DOM加载后执行的脚本,例如依赖于DOM元素的初始化代码。
      <script src="script.js" defer></script>
      

2、如何能有效地优化资源加载,提高web页面性能和用户体验?

1、懒加载(Lazy Loading)

​ 延迟加载图片和其他不可见的元素,减少初始加载时间。

<img src="image.jpg" loading="lazy" alt="example image">

2、defer与async应用

如上面试题解释

3、type=module方式

使JavaScript模块化,模块默认异步加载,不阻塞HTML解析 允许在浏览器环境中使用 ES6 模块,即导入(import)和导出(export)语句

示例1:<script type="module" src="script.js"></script>
示例2:
<script type="module">
  import { aa } from './script.js';
  document.addEventListener('DOMContentLoaded', () => {
    document.getElementById('bb').innerText = aa();
  });
</script>

4、<link rel="preload"> 预加载 提前加载资源,以提高页面加载性能

<link rel="preload" href="style.css" as="style">
<link rel="preload" href="script.js" as="script">

预加载的资源只是提前下载,并不改变它们原本的执行时机。需要在合适的地方使用相同资源的引用来执行或应用。

我的原创博文地址: blog.csdn.net/huazi99/art…