编码解码形成DOM树的过程
Posted liea
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编码解码形成DOM树的过程相关的知识,希望对你有一定的参考价值。
浏览器从网络或硬盘中获得html
字节数据后会经过一个流程将字节解析为DOM
树:
- 编码: 先将HTML的原始字节数据转换为文件指定编码的字符。
- 令牌化: 然后浏览器会根据HTML规范来将字符串转换成各种令牌(如
<html>
、<body>
这样的标签以及标签中的字符串和属性等都会被转化为令牌,每个令牌具有特殊含义和一组规则)。令牌记录了标签的开始与结束,通过这个特性可以轻松判断一个标签是否为子标签(假设有<html>
与<body>
两个标签,当<html>
标签的令牌还未遇到它的结束令牌</html>
就遇见了<body>
标签令牌,那么<body>
就是<html>
的子标签)。 - 生成对象: 接下来每个令牌都会被转换成定义其属性和规则的对象(这个对象就是节点对象)。
- 构建完毕: DOM树构建完成,整个对象集合就像是一棵树形结构。可能有人会疑惑为什么
DOM
是一个树形结构,这是因为标签之间含有复杂的父子关系,树形结构正好可以诠释这个关系(CSSOS
同理,层叠样式也含有父子关系。例如:div p {font-size: 18px}
,会先寻找所有p
标签并判断它的父标签是否为div
之后才会决定要不要采用这个样式进行渲染)。
整个DOM
树的构建过程其实就是: 字节 -> 字符 -> 令牌 -> 节点对象 -> 对象模型,下面将通过一个示例HTML
代码与配图更形象地解释这个过程。
如下面的这段HTML
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="style.css" rel="stylesheet">
<title>Critical Path</title>
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg"></div>
</body>
</html>
优化工作清单
当出现了页面性能问题时,或者在设计我们的应用之前,就可以参考如下的条目进行快速检查。
- 页面内容
- 减少 HTTP 请求数
- 减少 DNS 查询
- 避免重定向
- 缓存 Ajax 请求
- 延迟加载
- 预先加载
- 减少 DOM 元素数量
- 划分内容到不同域名
- 尽量减少 iframe 使用
- 避免 404 错误
- 服务器
- 使用 CDN
- 添加 Expires 或 Cache-Control 响应头
- 启用 Gzip
- 配置 Etag
- 尽早输出缓冲
- Ajax 请求使用 GET 方法
- 避免图片 src 为空
- Cookie
- 减少 Cookie 大小
- 静态资源使用无 Cookie 域名
- CSS
- 把样式表放在
<head>
中 - 不要使用 CSS 表达式
- 使用
link
替代@import
- 不要使用 filter
- 把样式表放在
- javascript
- 把脚本放在页面底部
- 使用外部 JavaScript 和 CSS
- 压缩 JavaScript 和 CSS
- 移除重复脚本
- 减少 DOM 操作
- 使用高效的事件处理
- 图片
- 优化图片
- 优化 CSS Sprite
- 不要在 HTML 中缩放图片
- 使用体积小、可缓存的 favicon.ico
- 移动端
- 保持单个文件小于 25 KB
- 打包内容为分段(multipart)文档
优化关键渲染路径
假设有一个HTML
页面,它只引入了一个CSS
外部文件:
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="style.css" rel="stylesheet">
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg"></div>
</body>
</html>
首先浏览器要先对服务器发送请求获得HTML
文件,得到HTML
文件后开始构建DOM
树,在遇见<link>
标签时浏览器需要向服务器再次发出请求来获得CSS
文件,然后则是继续构建DOM
树和CSSOM
树,浏览器合并出渲染树,根据渲染树进行布局计算,执行绘制操作,页面渲染完成。
有以下几个用于描述关键渲染路径性能的词汇:
- 关键资源:可能阻塞网页首次渲染的资源(上图中为2个,
HTML
文件与外部CSS
文件style.css
)。 - 关键路径长度: 获取关键资源所需的往返次数或总时间(上图为2次或以上,一次获取
HTML
文件,一次获取CSS
文件,这个次数基于TCP
协议的最大拥塞窗口,一个文件不一定能在一次连接内传输完毕)。 - 关键字节:所有关键资源文件大小的总和(上图为
9KB
)。
接下来,案例代码的需求发生了变化,它新增了一个JavaScript
文件。
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="style.css" rel="stylesheet">
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg"></div>
<script src="app.js"></script>
</body>
</html>
JavaScript
文件阻塞了DOM
树的构建,并且在执行JavaScript
脚本时还需要先等待构建CSSOM
树,上图的关键渲染路径特性如下:
- 关键资源: 3(
HTML
、style.css
、app.js
) - 关键路径长度: 2或以上(浏览器会在一次连接中一起下载
style.css
和app.js
) - 关键字节:11KB
现在,我们要优化关键渲染路径,首先将<script>
标签添加异步属性async
,这样浏览器的HTML
解析器就不会阻塞这个JavaScript
文件了。
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="style.css" rel="stylesheet">
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg"></div>
<script src="app.js" async></script>
</body>
</html>
- 关键资源:2(
app.js
为异步加载,不会成为阻塞渲染的资源) - 关键路径长度: 2或以上
- 关键字节: 9KB(
app.js
不再是关键资源,所以没有算上它的大小)
接下来对CSS
进行优化,比如添加上媒体查询。
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="style.css" rel="stylesheet" media="print">
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg"></div>
<script src="app.js" async></script>
</body>
</html>
- 关键资源:1(
app.js
为异步加载,style.css
只有在打印时才会使用,所以只剩下HTML
一个关键资源,也就是说当DOM
树构建完毕,浏览器就会开始进行渲染) - 关键路径长度:1或以上
- 关键字节:5KB
优化关键渲染路径就是在对关键资源、关键路径长度和关键字节进行优化。关键资源越少,浏览器在渲染前的准备工作就越少;同样,关键路径长度和关键字节关系到浏览器下载资源的效率,它们越少,浏览器下载资源的速度就越快。
其他JS在线测试网站
以上是关于编码解码形成DOM树的过程的主要内容,如果未能解决你的问题,请参考以下文章