重学JavaScript高级(二):深入浏览器的渲染原理

深入浏览器的渲染原理

网页的解析过程

image-20231230145257598.png

  • 在浏览器输入一个域名后,会通过DNS服务器解析成相应的IP地址
  • 通过IP地址访问对应的服务器
  • 目标服务器会返回相关文件
  • 浏览器在解析html文件的时候,遇到引入的css样式以及引入的script文件,都会从静态服务器中再次下载

浏览器渲染流程

image-20231230154857118.png

解析一 :解析HTML文件,生成DOM Tree

  • 浏览器在拿到服务器返回的index.html文件后
  • 会解析HTML,将其解析成为DOM Tree

在解析CSS文件的时候,不会影响DOM Tree的解析

解析二 :生成CSS规则

  • 在解析过程中,如果遇到CSS的link元素,那么会由浏览器下载对应的CSS文件

    • 下载CSS文件不会影响DOM Tree的生成
  • 浏览器在下载完CSS文件之后,就会解析CSS,生成相应的规则树

    • 我们可以称之为CSSOM

解析三 :构建Render Tree

  • 当有了DOM Tree 和CSSOM Tree 就可以将两个结合,一同构建Render Tree了

  • 注意:

    • link元素不会阻塞DOM Tree的构建过程,但是在理论上会阻塞Render Tree的构建
    • Render Tree和DOM Tree并不是一一对应的关系,比如某些元素设置成了dispaly:none,就不会在Render Tree中显示

解析四 :布局(layout)和绘制(paint)

  • 在得到Render Tree之后,就会在上面运行布局,用来计算每个节点的几何体

    • 渲染树会记录显示哪些节点以及其他样式,但是不记录每个节点的尺寸、位置等信息
    • 布局是确定每个节点的高度、宽度和位置信息
  • 将每个节点绘制到屏幕上

    • 在绘制阶段,浏览器将布局阶段计算的每个frame转为屏幕给上实际的像素点
    • 包括将元素的可见部分进行绘制,比如文本、颜色、边框等

回流和重绘解析(性能优化)

  • 理解回流reflow

    • 第一次确定了节点的大小和位置,称之为布局
    • 在之后的操作,引起了节点大小、位置修改重新计算,称之为回流
  • 引起回流的情况

    • 比如DOM结构发生了变化(添加或者移除节点)
    • 改变了布局(修改了width、height、padding、font-size)
    • 修改了窗口尺寸
  • 理解重绘(repaint)

    • 第一次渲染内容称之为绘制
    • 之后重新渲染称之为重绘
  • 引起重绘的原因

    • 比如修改背景颜色,文字颜色,边框颜色,样式等
    • 总之对布局以及大小没有修改
  • 两者之间的关系

    • 回流一定会引起重绘,所以回流是十分消耗性能的事
  • 避免回流的方法

    • 修改样式时,尽量一次性修改:通过cssText修改,比如通过添加class属性进行

    • 避免进行频繁的DOM操作:我们可以将多次DOM操作,通过DocumentFragment转化成一次DOM操作

    • 尽量避免通过getComputedStyle获取尺寸,位置等信息

    • 对某些元素使用position中的absolute或者fixed定位

      • 此种方法也会引起回流,但是开销相对会小,不会对其他的元素造成影响

合成和性能优化(性能优化)

特殊解析-composite合成

  • 首先要了解图层,在Chrome浏览器中,F12可以查看当前界面的图层

image-20231230164704568.png

  • 默认情况下,标准流中的内容都会被绘制在同一个图层之中(layer)

  • 而一些特殊的属性,会创建一个新的合成层,并且新的合成层可以利用GPU来加速绘制

    • 因为每个合成层都是单独渲染的
  • 以下属性可以形成新的合成层

    • 3D transforms
    • viedo、canvas、iframe
    • opacity动画转换时
    • position:fixed
    • will-change
  • 注意:分层可以提高性能,但是是以内存管理为代价,因此不应该作为web性能优化策略而过度使用!!

defer和async

script元素处理

  • 通过以上学习,我们知道浏览器在解析HTML文件的时候,遇到link的时候,不会影响解析DOM
  • 但是遇到script元素的时候,首先下载JavaScript,浏览器就会停止加载DOM Tree
  • 只有等待JavaScript脚本执行结束后,才会继续解析HTML,构建DOM树
  • 那么为什么会出现以上现象?

    • 因为js作用之一就是操作DOM,并且可以修改DOM
    • 如果我们等到DOM树构建完成且渲染完之后,再执行JavaScript,会造成严重的回流和重绘,影响页面的性能
    • 所以会在遇到script元素时候,优先下载和执行JavaScript代码,再继续构建DOM树
  • 在现代页面开发中,这种形式会带来新的问题

    • 在目前开发模式中(Vue、React)脚本往往比HTML页面更重,处理时间会更长
    • 所以会造成页面的解析阻塞,在脚本下载、执行完成之前,用户在界面上什么都看不到
  • 为了解决当前的问题,script元素提供了两个属性defer和async

defer (下载完,等待DOM Tree的构建完成再执行)

  • 告诉浏览器不要等待脚本的下载,而是继续解析HTML,构建DOM Tree

    • 在遇到 有defer属性的script的脚本,浏览器会下载脚本,但是不会阻塞DOM Tree的构建
    • 如果脚本提前下载好了,会在DOM Tree构建完成之后,DOMContentLoaded事件之前执行defer中的代码
    • 所以 DOMContentLoaded中的代码总是会等待defer中的代码执行完之后再执行
    • 另外 多个defer脚本会按照顺序依次执行
    • 从某种角度来说,defer可以提高页面的性能,推荐写在head元素中

async (下载完,立即执行)

  • 让一个脚本完全独立
  • 浏览器遇到async不会阻塞DOM Tree的构建(与defer类似)
  • 但是 async属性的脚本,在下载完成之后会立即执行,不能保证其执行的时机
  • 同时,多个async的脚本在一起的时候,不能保证其时机
  • 因此,defer里面的脚本,通常可以写一些DOM操作,并且对脚本执行顺序有要求的代码;而async中写一些与DOM无关,且不用保证执行时机的代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值