从输入url到浏览器显示页面,中间经历过什么过程?
- 当前页面即将被替换成新页面,浏览器给当前页面一次执行 beforeunload事件的机会,事件允许页面在退出之前执行一些清除操作,或者询问用户是否要离开当前页面。
- DNS(域名)解析:优先查找缓存,如果 DNS 已经缓存了直接过,否则不断溯源向上查找,直到找到为止(顺序:浏览器-操作系统-路由)
- tcp链接(三次握手)
- 发送HTTP请求,如果是HTTPS还需建立SSL,如果是H2则会判断是否支持H2,否则降级HTTP1.x
- 返回HTML并解析
- 从上至下解析HTML、CSS,生成对应的DOM树、CSS树,解析树生成render tree
- 开始计算每个 box 的样式,进行重绘重排绘制页面
浏览器的渲染过程是怎样的?
- 构建DOM,字节 -> 字符串 -> 解析Token -> 编译Node -> DOM
- 构建CSSOM,字节 -> 字符串 -> 解析Token -> 编译Node -> CSSOM
- 何称DOM tree 和 CSS rule tree,转换为render tree(会过滤display: none 这样的节点)
- 重排/回流
- 重绘
重排/重绘是什么?重排/重绘触发条件?有哪些API会触发重排?
- 重排:改变布局导致渲染树需要重新计算(offset、margin、top)
- 重绘:元素外观改变所触发的浏览器行为(background\color\opcity)
- 重排一定会重绘,重绘不一定会重排。
如何尽可能减少重排?
- 减少JS对于样式的操作,如果需要样式操作可以批量操作,不要for循环一个个设置。设置CSS可以使用cssText,不要一个一个属性设置。
- 减少CSS选择器的嵌套。
- 如果有需要位移,可以开启GPU加速,使用transform来做。减少样式层级。
浏览器的HTML/CSS/JS解析过程是怎样的?
- 浏览器依次执行DOM并解析,如果碰见了非defer以外的JS外联,CSS外联脚本会阻碍HTML的解析,先下载并执行JS和CSS。
- 浏览器解析CSS为从右向左的顺序,为什么从右向左?从右向左依次收敛查找范围,性能更好。
- 浏览器解析JS则有两个阶段,第一个为预解析,预解析就是我们通常所说的变量提升的阶段,会先扫一遍代码把变量函数啥的都先预解析一遍,然后在逐行解析执行。
所以如何优化我们的HTML解析呢?
- 减少DOM数量,减少必须加载的HTML,JS和CSS代码
- 减少复杂CSS选择器,减少对DOM的重绘和回流,提升浏览器render性能
- 异步加载JS或者延迟加载JS,可以放在body最末尾,可以动态创建JS加载,可以defer加载JS
- 由于在JS中可能会读取CSS的值,所以CSS的加载其实会影响DOMContentLoaded事件的触发时间,如果CSS在JS之前加载,JS会等待CSS加载完成,而HTML虽然不会等待,但是由于JS会等待导致DOMContentLoaded事件依旧会延迟。