当浏览器的网络线程收到 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
用法如:
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…