一 页面的加载和渲染过程
当我们在浏览器地址输入一个URL,最终会呈现一个完整页面,大概会经历以下步骤:
域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户
1.1 HTML 加载
输入URL后首先拿到的是HTML,所以最先下载的是HTML,下载以后会对它进行解析.
1.2 其他静态资源下载
HTML在解析过程中,如果HTML引用其他的外部资源链接,如:JS和CSS和图片时,会启动别的线程来下载这些资源. 特殊的是,当遇到js文件时,HTML的解析会停下来,等JS文件下载完后再进行解析,因为JS有可能改变DOM的结果,重复操作,有白白浪费资源的风险,因此HTML解析器等JS下载完后再进行解析
1.3 DOM树构建
在HTML解析时候,解析器会把HTML解析成一个个DOM对象,而这些DOM最终会构建DOM 树。
1.display的元素,注释存在于DOM树中
2.js会阻塞DOM树的构建从而阻塞其他资源的并发加载,因此最好把JS放在最后加载
3.对可能异步加载的JS使用 async 和defer
复制代码
1.4 CSSOM 树构建
在CSS下载完后,CSS解析器会对CSS进行解析,会CSS解析成CSS对象,最终构建把这些CSS组装起来,构建CSSOM树。
1\. js 会阻塞cssom的构建,只有js访问才会阻塞
2\. cssom树的构建和dom树的构建是并行的
3\. 减少css的嵌套(最好6层以内)和定义合理的css可以提高解析速度
复制代码
1.5 渲染树构建
DOM树和CSS构建完成后,浏览器会根据这两棵树再构建一颗渲染树,它包含了可见的dom节点和节点的样式
1.渲染树的根节点是HTML节点
2.renderObject和dom不是完全对应的,不可见元素display:none是不会放入渲染树中的
3.visibility:hidden 的元素在Render Tree中
复制代码
1.6 布局计算
渲染树构建完成后,所有的元素关系需要和应用样式关联,计算器会计算元素的大小和绝对位置.
1.float,flexd,absolute的元素会发生偏移
2.我们常说的脱离文档流,就是脱离布局。
复制代码
1.7 绘制(Paint)
布局计算完成后,浏览器就可以在页面上渲染了,整个页面就呈现在屏幕上了.
1.8 重排(Reflow)与重绘(Replain)
渲染树是动态构建的,DOM节点和CSS节点的任何改变都会导致渲染树的重新构建,渲染树的改动就会导致重排与重绘
-
重排
当我们在DOM树中新增,修改,删除,或者改变某些元素大小,位置,布局方式的时候,都要重新计算. 在改动发生时,要重新经历DOM的改动,CSSOM的构建,渲染树的构建,布局计算和绘制整个流程,这个过程就叫 "重排" ,有点也就 "回流"
回流的触发
1.dom元素的位置和大小发生改变
2.dom元素的增加和删除
3.伪类的激活
4.窗口大小的改变
5.增加和删除class样式
6.动态计算修改class样式
浏览器并不会每一次reflow都会执行,而是会积攒一部分,这个过程也被成为异步reflow,或者增量异步reflow. 但是有些情况浏览器是不这样做的,比如 resize 窗口,改变页面默认的字体等这些操作,浏览器会马上 reflow
复制代码
-
重绘
重绘是我们改动元素的字体颜色,背景色等外观元素时候,并不会改变它的大小,也不会影响其他元素的布局,这个时候就不需要重新构建渲染树。浏览器会对元素的样式重新绘制,这个过程叫做 "重绘"
重绘的触发: 任何对元素样式,如color,background-color等熟悉的改变,JS和CSS都会引起重绘。
二.前段性能优化总结
2.1 页面加载优化
-
减少HPPT 请求
尽量减少 页面的请求数(首次加载同时请求数不能超过4个),移动设备浏览器同时响应请求为四个请求(Android支持四个,IOS 5+ 支持6个)
合并JS和CSS
使用 CSS 精灵图
-
使用CDN
CDN(内容发布网络)是一组分布在多个不同地理位置的Web服务器,用于更加有效地向用户发布内容。在优化性能时,向特定用户发布内容的服务器的选择基于对网络慕课拥堵的测量
-
缓存资源 添加Expires头
使用缓存可减少向服务器的请求数,节省加载时间,所有的静态资源都要在服务器端设置缓存,并且使用长缓存(使用时间戳更新缓存)
-
压缩代码
减少资源大小可以加快网页显示速度,对代码进行压缩,并在服务器端设置Gzip
-
无阻赛
头部内联的样式的样式和脚本会阻塞页面的渲染,样式放在头部并用 link 方式引入,脚本放在尾部 并用异步方式加载
-
按需加载
讲不影响首屏的资源和当前屏幕不用的资源放在用户需要时才加载,可大大提升显示速度和降低总体流量
-
减少Cookie
Cookie会影响加载速度,静态资源域名不适用Cookie
-
避免重定向
当页面发生了重定向,就会延迟整个HTML文档的传输。在HTML文档到达之前,页面中不会呈现任何东西,也没有任何组件会被下载。
2.2 执行优化
-
CSS 写在头部,JS写在尾部异步执行
将样式表放在头部对于实际页面加载的时间并不能造成太大影响,但是这会减少页面首屏出现的时间,使页面内容逐步呈现,改善用户体验,防止“白屏”
脚本放在底部对于实际页面加载的时间并不能造成太大影响,但是这会减少页面首屏出现的时间,使页面内容逐步呈现。
js的下载和执行会阻塞Dom树的构建(严谨地说是中断了Dom树的更新),所以script标签放在首屏范围内的HTML代码段里会截断首屏的内容。
-
避免img,iframe 等的src为空,为空会重新加载当前页面,影响速度和效率
-
尽量避免重置图像大小:多次重置图像大小会引发图像的多次重绘,影响性能
-
图像尽量避免使用DataURL
2.3 样式优化
-
避免在HTML 中书写style
-
避免CSS 表达式
-
使用flexbox 代替传统的布局模型
-
正确使用 display熟悉
-
不声明过多的 font-size
-
值为0时不需要任何单位
-
避免让选择符看起来像正则表达式:高级选择符执行耗时长且不易读懂,避免使用
2.4 渲染优化
-
HTML 使用 viewport :viewport 可以加速页面的渲染
-
减少 DOM 节点:DOM 节点太多影响页面的渲染,应尽量减少 DOM 节点
-
动画优化 尽量使用 CSS3 动画
-
合理使用 requestAnimationFrame 动画代替 setTimeout
-
使用 requestAnimationFrame 监听帧变化,使得在正确的时间进行渲染;
-
高频事件优化:Touchmove 和 Scroll 事件可导致多次渲染
函数节流
函数防抖
使用requestAnimationFrame监听帧变化:使得在正确的时间进行渲染
增加响应变化的时间间隔:减少重绘次数
-
GPU加速:使用某些HTML5标签和CSS3属性会触发GPU渲染,请合理使用(过渡使用会引发手机耗电量增加)
HTML标签:video、canvas、webgl
CSS属性:opacity、transform、transition
2.5 JavaScript执行优化
-
减少重绘和回流
-
减少不必要的DOM操作
-
尽量改变class 而不是Style,使用classList 代替 className
-
缓存DOM与计算,每次DOM 选择都要计算,用一个变量保存这个值
-
尽量使用事件代理
转载自:https://juejin.im/post/6844904004300832775#11-html-%E5%8A%A0%E8%BD%BD
网友评论