从web浏览器的渲染到性能优化
来源:互联网 发布:godaddy 获取域名证书 编辑:程序博客网 时间:2024/05/28 23:23
本文主要讲解web浏览器的渲染原理、流程到性能优化。主要有以下几点:
(1) script标签中的属性defer和async的区别
(2) 浏览器的渲染顺序
(3) 如何防止阻塞DOM渲染
(4) 如何保证首屏优化、关键渲染路径优化
(5) 如何从浏览器渲染、网络请求、js引擎机制优化性能
一: script标签中的属性defer和async的区别
要想让script标签中的defer和async属性生效,必须引入属性src,即js文件必须是外部引入的脚本文件。
下面讨论两个基本点:
(1) 下载时是否会阻塞DOM的渲染
(2) 执行时是否会阻塞DOM的渲染
首先谈一下async属性的特性:
(1) async属性是赋予脚本异步属性
(2) 页面一加载的时候,就立即下载脚本,不妨碍页面中的其他操作,比如下载其他资源、等待加载其他脚本
(3) js一旦下载好,就会立即执行
(4) 和文档同时呈现,标记为async的js脚本不会按照顺序执行
(5) 一般js不需要改变页面的DOM的时候,可以使用属性async进行异步加载
(6) 注意,异步脚本不要在加载期间修改DOM。有async属性的脚本,下载的时候不会阻塞DOM的解析,但是执行的时候会阻塞页面的解析
(7) 具有async属性的js脚本一定会在页面的load事件前执行,,但可能会在DOMContentLoaded事件触发之前或之后执行
其次谈一下defer属性的特性:
(1) defer属性赋予脚本延迟属性
(2)页面一加载的时候,就立即下载具有defer属性的js脚本,下载期间不阻塞DOM的解析,但等到整个DOM都解析完成之后才运行具有defer属性的JS脚本
(3) 下载的时候不阻塞DOM解析,执行具有defer属性的js时候也不会阻塞DOM的解析
(4) 具有defer属性的JS脚本会按照书写的前后顺序执行,因此脚本具有前后依赖关系可以放心使用(在实际中具有defer属性的脚本并不一定会按照书写顺序执行,所以最好是只让一个js脚本具有defer属性)
(5) 具有defer属性的js脚本会先于DOMContentLoaded事件执行(实际当中,也不一定会在DOMContentLoaded事件前执行)
现在总结一下async和defer属性的共同点:
(1) 两者在下载的时候都不会阻塞DOM解析
(2) 两者都只对外部脚本有效,如<script src='index.js' defer='defer' ></script>或者<script src='index.js' async='async' ></script>
(3) 都可以使用onload事件进行一系列处理
现在总结一下async和defer属性的不同点:
(1) 不具有async和defer属性的js脚本,浏览器根据其所在位置阻塞解析,被下载紧接着执行,直到完成。
(2) 具有async属性的js脚本,在下载的时候不会阻塞DOM的解析。但是js文件一旦下载后之后,就会立即执行脚本,此时有可能会阻塞DOM的解析。即具有async属性的js脚本下载时候不会阻塞DOM的解析,但在执行的时候有可能会阻塞DOM的解析。
(3) 具有defer属性的js脚本,在下载的时候不会阻塞DOM的解析。js加载完之后,等待DOM渲染完成之后在执行js脚本,此时不会阻塞DOM的解析。即具有async属性的js脚本下载和执行的时候都不会阻塞DOM的解析。
两者的应用场景
(1) 具有async属性的js脚本,适合基本没有DOM操作、和模块的加载顺序无关、执行时间要短,否则对首屏还是有很大的影响的。
(2) 具有defer属性的js脚本,按序加载,加载和执行的时候都不会阻塞DOM的解析。
二:浏览器关键渲染顺序
接下来让我们来思考几个问题:
(1) 具有async属性的js脚本可能会阻塞DOM的解析,那么css在加载的时候回阻塞DOM的解析吗?
(2) 其他资源如何下载?
(3) 其他资源会阻塞DOM的解析吗?
(4)DOM parse是什么?
(5) 事件DOMContentLoaded和load分别是基于那个节点触发的?
首先让我们来看一下浏览器的渲染过程
下图展示了整个浏览器的渲染过程
(1) 文档对象模型(DOM)
上图展示了在浏览器里面,html的字节码被转换成DOM的过程
A、Bytes->Characters转换:根据字节Bytes的编码规则,将其转换为特定的字符Characters
B、Characters->Tokens(生成Tokens):将Characters转化为w3c定义的各种特定标签,生成Tokens(令牌)
C、Tokens->Nodes(词法解析):匹配字符串,将Tokens按照规则转换成节点对象(Nodes),其具有属性和规则
D、Nodes->DOM(DOM构建):根据每个节点的层次关系和属性,转换为直观的树形结构,具有明确的父子关系
至此,得到页面完整的DOM模型,以后的页面渲染(Render Tree)包括布局(Layout)和绘制(Paint)都是基于DOM的
注意:HTML都是增量构建的,在HTML文件还在传输的时候,HTML parse就已经开始了。
DOM代表页面的结构,决定整个初始化页面的布局;CSSOM决定页面的样式
(2) CSS对象模型(CSSOM)
如上图所示是CSSOM构建流程图,将css文件的字节码转换为符合浏览器特定规则的字符,然后浏览器对其解析和构成树。整个计算的过程包括一套复杂的特异度计算规则(css属性来源->特异度大小->书写顺序前后覆盖),最终确定每个节点的样式值,形成CSSOM。 css被认为 是一种渲染阻塞资源(所谓的CSS白屏),因为渲染树是依赖CSSOM才能生成,然后才到浏览器的布局渲染流程,因此才将css放到head标签里面。
(3) 渲染树(Render Tree)
渲染树生成的大概过程如下:
A、从DOM的根节点开始遍历每个在HTML和CSS上的可见节点
B、对每个可见节点,为其找到适配的CSSOM并且组合他们
C、将每个节点(包括内容和样式)组建成Render Tree
所谓的可见节点:渲染树包含了渲染网页所需的所有节点,不需要渲染的节点是不会合并到渲染树里面的,比如元数据元素meta,base等,设置display:none的节点
(4) 布局(Layout)-计算渲染树节点大小
布局的最终效果是形成一个“盒子模型”,他需要精确地计算出每个元素所占据的位置坐标,将相对测量值(rem,vw,vh,em)转换成绝对像素。
下面讲解一下相对测量值的转换规则:
A、rem是相对根元素<html>的font-size值确定大小的;
B、vw,vh是相对视窗口的大小来确定的
我们可以在js里面改变节点的样式,但是css元素的位置和大小改变的,从而改变整体布局的话,那么浏览器会重新布局和渲染,这在开发过程中要注意避免和减小性能损耗的。
(5) 绘制(Paint)
根据background,border,box-shadow等样式和HTML内容,将Layout生成的区域填充为最终显示在屏幕上的像素
注意:DOMContentLoaded发生在DOM树构建完成之后发生的,也就是DOM解析完</html>的那一刻。load事件则是在所有资源都加载渲染之后才会触发
三、优化关键渲染路径
优化关键渲染路径是指优先显示与用户当前操作有关的内容。
1、CSS阻塞渲染
转载路径:http://blog.csdn.net/allenliu6/article/details/76609929
- 从web浏览器的渲染到性能优化
- 从web浏览器的渲染到性能优化
- 【Web渲染性能优化】渲染管道
- 从浏览器的渲染原理讲CSS性能
- 从浏览器的渲染原理讲CSS性能
- 从GPU到3D渲染:游戏图形渲染技巧与性能优化
- 从浏览器渲染谈页面优化
- Web性能优化-浏览器端
- java web 性能优化----浏览器优化
- 最常被遗忘的 Web 性能优化:浏览器缓存
- 必须了解的浏览器渲染性能
- 浏览器渲染流水线解析与网页动画性能优化
- web性能优化:详说浏览器缓存
- web性能优化:详说浏览器缓存
- 从IplImage到QImage的转化看性能优化
- 性能优化--从Json过度到FlatBuffers的数据传输
- 优化浏览器渲染
- 优化浏览器渲染
- android 关于TimeZone的小运用根据時間帯、变换表示時間
- Zookeeper日志配置以及集群搭建
- 检查DLL或EXE依赖项
- (原创)js,ajax与springboot之间的两种传参方式
- Hadoop安装(一)zookeeper集群安装
- 从web浏览器的渲染到性能优化
- Git Rebase和Merge异同
- windows服务安装启动报错误1053:服务没有及时响应启动或控制请求
- SoapUI测试Https请求,解决问题SSLPeerUnverifiedException: peer not authenticated
- Linux进程监控 + 钉钉通知
- [Spring Boot 系列] 集成maven和Spring boot的profile功能
- 环境搭建、IDE选择、学习方法的思考
- 【Android Things】第一节 创建第一个工程
- jQuery图片预加载(延迟加载)之插件Lazy Load