了解浏览器底层渲染机制

浏览器渲染机制

浏览器底层渲染机制:指的是当我们在url地址栏输入网址,到看到页面中间都经历了哪些事情,本次说的是当浏览器拿到数据到看到页面都做了那些事情

CRP(critical rendering path):关键渲染路径;渲染的机制和步骤,去详细地进行每一步的优化,以此来提高页面的渲染速度和运行性能。

页面之所以能渲染

  1. 从服务器获取到需要渲染的内容(URL解析/DNS/TCP/HTTP…)
  2. 浏览器会基于自己的渲染引擎(例如:webkit/gecko/trident/blink…)开始自上而下加载渲染代码

从服务器获取的是文件流(进制代码的内容)

  1. 浏览器首先会把16进制的字节信息编译为“代码字符串”
  2. 按照W3C规则进行字符串解析,生成对应的Tokens,最后转换为浏览器内核可以识别渲染的DOM节点(词法解析)
  3. 按照节点最后解析为对应的树 DOM TREE / CSSOM TREE

浏览器拿到代码后自上而下渲染解析,声明文档标识,声明HTML,HEAD,TITLE…

进程 VS 线程

  • 进程:指的是一个应用程序(浏览器打开一个页面,就相当于开了一个进程)
  • 线程:指的是应用程序中具体做事情的(进程当中具体去执行事物的东西)

一个进程可能包含多个线程浏览器打开页面会开辟一个进程(每一个页面都是一个进程),浏览器本身是多线程,有多个线程就能同时做很多事情,一个线程同时只能干一件事情。
浏览器可以开辟多个线程 / 进程的:

  • 渲染页面的GUI渲染线程
  • 渲染JS代码的JS引擎线程
  • 从服务器获取资源和数据的HTTP网络线程(可以开辟多个)
  • 定时器监听线程
  • DOM监听线程

同步编程 VS 异步编程
同步编程:一般只有一个线程去处理事情,上面的事情处理不完,下面的事情无法处理(一件一件事情的去干)
异步编程:

  • 多线异步编程
  • 单线异步编程(JS是EventQueue+EventLoop机制完成单线异步编程的)

CSS样式的方式

  • 行内样式:一般不考虑 ,不易维护,代码量大。
  • 内嵌式<style> ...</style>
  • 外链式:link和@import都是导入外部样式(从服务器获取样式文件)

页面渲染过程中

  • 如果是style内嵌样式,GUI直接渲染
    • 如果代码量少,直接用内嵌,拉取CSS同时CSS也拉取回来了,渲染的直接就渲染了
    • 如果CSS代码比较多,内嵌会影响HTML的拉取速度,不利于代码维护,所以用外链的方式比较好。
  • 遇到link,浏览器会开辟一个新的HTTP线程去加载资源文件信息,同时GUI渲染线程会继续向下渲染代码,不论CSS是否请求回来,代码继续渲染(异步)
    • 浏览器同时发送的HTTP请求是有数量限制的(谷歌约5至7个)
    • 超过最大并发限制的HTTP请求需要排队等待
    • HTTP请求越少越好
  • 遇到的是@import ,浏览器开辟一个HTTP线程去服务器请求资源文件,GUI渲染线程会暂时停止渲染,资源文件没有返回之前,是不会继续渲染的 @import阻碍浏览器的渲染,项目中尽量少用(同步)
  • 遇到<script src="xxx.js"></script>:阻碍GUI的渲染,可以添加一些事件解决这个问题
    • window.addEventListener(“load”,function(){}):等待页面所有资源都加载完再触发执行
    • window.addEventListener(“DOMContentLoaded”,function(){}):等待DOM树渲染完即可触发执行,优先load触发
    • async : <script src="xxx.js" async></script> 请求JS资源是异步的[单独开辟HTTP去请求],此时GUI渲染继续;但是一旦当JS请求回来,会立即暂停GUIde处理,接下来去渲染JS…
    • defer : <script src="xxx.js" defer></script> 和Link是类似的,不会阻碍GUI渲染,当GUI渲染完,才会把请求回来的JS去渲染…

* 假如有五个JS请求,如果不设置任何属性,肯定是按照顺序请求和渲染JS的【依赖关系是有效的】;但是如果设置async,谁先请求回来就先渲染谁,依赖关系无效;如果使用defer是可以建立依赖关系的(浏览器内部在GUI渲染完成后,等待所有设置defer的资源都请求回来,在按照编写的的依赖顺序去加载js。
* 真实项目开发中,一般把link放在页面的头部【为了在没有渲染DOM的时候,就通知HTTP去请求CSS,这样DOM渲染完,CSS差不多也就回来了,更有效利用时间,提高页面的渲染速度】;把JS放在页面的底部,防止其阻碍GUIde渲染,如果不放在底部,我们最好设置async / defer。 async / defer加载发生在load之前,DOMcontentLoad之后触发

构建DOM树、CSSOM树、RENDER树

  • 转换:把进制数据转换成代码字符串
  • 词法解析:依托W3C规范生成对应的节点
  • DOM、CSSOM构建:根据节点生成层对应的树

【DOM树】
在这里插入图片描述
【CSSOM树】
在这里插入图片描述
【Render-Tree渲染树】
在这里插入图片描述
步骤总结

  • 处理HTML标记,构建DOM树
  • 处理CSS标记,构建CSSOM标记
  • 将DOM树和CSSOM树融合成渲染树
  • 根据生成的渲染树,计算他们在设备视口(viewport)内的确切位置和大小,这个计算的阶段的阶段就是回流 =>布局(Layout)或者重排/回流(reflow)
  • 根据渲染树以及回流得到的几何信息,得到节点的绝对像素 =>绘制(painting)或栅格化(rasterizing)
    在这里插入图片描述
    浏览器页面渲染
  • 页面渲染的第一步:在CSS资源还没有请求回来之前,先生成DOM树(DOM的层级关系/节点关系)
  • 页面渲染的第二步:当所有的CSS都请求回来之后,浏览器按照CSS的导入顺序,以此进行渲染,最后生成CSSOM树
  • 页面渲染的第三步:把DOM树和CSSOM树结合在一起,生成有样式,有结构的RENDER TREE 渲染树
  • 最后一步:浏览器按照渲染树,在页面中进行渲染分析
    1) 计算元素在视口中的大小和位置 => 布局(Layout)或者重排/回流(reflow),第一次叫布局,以后需要重新计算叫重排或者回流
    2)根据渲染树以及回流得到的几何信息得到节点的绝对像素 =>绘制/重绘(painting)

这样才能看到所有页面内容了

Render-Tree(DOMContentLoaded事件触发)-> 执行JS -> CSSOM TREE ->RENDER TREE渲染树【浏览器未来是按照这个树来绘制页面的】,-> Layout布局计算【回流 / 重排】->Painting绘制【重绘】{分层绘制}

  • 页面第一次渲染,必然会引起一次回流和重绘
  • 如果我们改变了元素的位置和大小,浏览器需要重新计算元素在视口中的位置和大小信息,重新计算的过程是回流 / 重排,一旦发生了回流操作,一定也是会触发重绘【很消耗性能:DOM操作消耗性能,90%说的都是回流 / 重排】
  • 但是如果只是一些普通样式的改变,位置和大小不变,只需要重绘即可。

性能优化

  1. 减少DOM树渲染时间(HTML层级不要太深,标签语义化...)
  2. 减少CSSOM树渲染时间(选择器是从右到左解析的,所以尽可能减少选择器的层级【less/sass中的层级嵌套虽然好用 ,但是是一个大坑】)
  3. 减少HTTP的请求次数和请求大小(HTTP的资源文件有并发上线6~7)
  4. 一般会把CSS请求放在页面的开始位置(充分利用HTTP多请求并发机制),提前请求资源 用link 不用@import,对于移动端来讲,如果css比较少,尽量使用内嵌式)
  5. 为了避免白屏,进来第一件事,快速生成一套loading的渲染树(前端骨架屏:位置留好了,但是没有内容);服务器的SSR骨架屏所提高的渲染是为了避免客服端再次单独请求数据,而不是样式和结构上的(首屏处理)
  6. JS加载放到页面的底部,并且尽可能使用async或者defer 避免阻塞的JS加载

以上这些叫做CRP性能优化节点。

白屏
所谓白屏,就是当前设备打开页面,第一步从服务器请求回来HTML,然后渲染,渲染过程中请求CSS资源,生成DOM树、CSSOM树、Render-Tree渲染树,最后整个渲染页面,这个过程是需要时间的,从请求页面到整个所有东西没有完成之前所经历的时间会产生一个白屏的效果。
白屏优化:减少第一次页面渲染时间,包括后续打开时间,这些优化就是项性能优化的关键点。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值