浏览器渲染原理以及性能优化

    技术2023-09-25  103

    浏览器渲染原理以及性能优化

    浏览器渲染原理进程与线程Request请求阶段Response响应阶段浏览器渲染网页注意事项浏览器渲染网页阻塞顺序DOM的重绘和回流 Repaint & Reflow 原理图性能优化

    浏览器渲染原理

    进程与线程

    当我们打开一个网页的时候,就创建了一个进程一个进程可以同时干多件事,这就是多线程

    Request请求阶段

    DNS解析TCP协议的三次握手和四次挥手 拓展:HTTPS与HTTO的区别(HTTP2)

    Response响应阶段

    获得 HTTP状态码,304缓存(性能优化),HTTP报文开辟栈内存 当浏览器拿到代码后,浏览器在内存条中开辟出一块栈内存,用来给代码的执行提供环境,同时分配一个主线程去一行行的解析和执行代码 这就解释了为什么JS是单线程的,因为浏览器只会分配一个线程去解析与执行代码 一行行代码进栈执行,执行完之后出栈 如拿到网页后,我们首先解析到 ,会判断到这是一个html页面,然后这一行代码出栈,解析下一行代码。当遇到 link/script/img 等,会开辟全新的线程,去加载资源文件,从而形成一个任务队列这里面有个 微任务和宏任务 的概念CSS处理完成生成 CSSOM 也是一个树主任务队列(主线程)自上而下走完之后,只生成了DOM树,这个时候会去查看任务队列中什么完成了,完成之后就处理,处理完之后再去队列里面看直到完成为止。(事件循环)DOM树跟CSSOM结合后得到 Render Tree

    浏览器渲染网页注意事项

    DOM的构建过程是一个深度遍历的过程,即当前节点的所有子节点都构建好以后才会去构建当前节点的下一个兄弟节点

    渲染树和DOM不同,因为像DOM树中的display:none元素不会出现在渲染树中,但visibility: hidden会出现在渲染树中

    DOM解析和CSS解析是同时进行,互不影响

    渲染树的生成并不是等到DOM树和CSS规则树解析完成才开始合并,而是边解析、边合并渲染

    浏览器渲染网页阻塞顺序

    构建DOM树时,如遇到JS元素时,会阻塞DOM树和CSS规则树的构建,优先执行JS文件

    构建DOM树时,如遇到CSS元素时,会开启异步请求线程,该线程会先下载CSS文件,再构建CSS规则树,该线程会阻塞JavaScript引擎线程,但不会阻塞DOM树的构建

    CSS解析和JS解析互斥,也就是说JS解析时会阻塞CSS解析而CSS解析时也会阻塞JS解析

    JS解析时,如果JS还操作了CSS,而这个CSS还没有下载或构建解析,则会延迟执行JS,直到完成CSS下载构建解析,再会继续执行JS

    DOM的重绘和回流 Repaint & Reflow

    DOM的重绘 Repaint 元素样式的改变(但宽高,大小,位置并不变) 如 outline,visibility,color,background-color 等DOM的回流 Reflow 元素大小或者位置发生了改变(当页面布局和几何信息发生改变的时候),触发了重新布局,导致渲染树重新计算布局和渲染

    注意: 回流一定会触发重绘,而重绘不一定会回流

    原理图

    解析HTML,声称DOM树,解析CSS,生成CSSOM树将DOM树和CSSOM数结合,生成渲染树Layout(回流):根据生成的渲染树,计算它们在设备视口(viewport)内的确切位置和大小,之歌计算的阶段就是回流Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素Display:将像素发送到GPU,展示在页面上

    性能优化

    减少 HTTP 的请求次数和大小 资源合并压缩 (webpack)图片懒加载音视频走流文件 (m3u8) 避免DOM的回流 放弃传统操作dom的时代,基于vue/react开始数据影响视图模式(虚拟dom) mvvm / mvc / virtual dom / dom diff …分离读写操作(现代的浏览器都有渲染队列的机制)样式集中改变缓存处理let a = box.clientWidth; let b = box.clientHeight; box.style.width = a + 10 + 'px'; box.style.height = b + 10 + 'px'; 代码批量处理// 文档碎片 let frg = document.createDocumentFragment(); for (let i = 0; i < 5; i++) { let newLi = document.createElement('li'); newLi.innerHTML = i; // 创建的li放到文档碎片中 frg.appendChild(newLi); } // 一次性把所有的内容放到容器中,引发一次回流 box.appendChild(frg); frg=null; // 字符串拼接 let str = ``; for (let i = 0; i < 5; i++) { str+= `<li>${i}</li>`; } box.innerHTML=str; 动画效果应用到position属性为absolute或fixed的元素上(脱离文档流)CSS3硬件加速(GPU加速) 直接不要回流重绘, 使用 transform \ opacity \ filters … 这些属性会触发硬件加速,不会引发回流和重绘… 牺牲平滑度换速度避免table布局和使用css的javascript表达式

    本文为跟着周啸天老师的课程所编写的笔记

    Processed: 0.009, SQL: 9