欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浏览器底层渲染机制

程序员文章站 2022-04-14 14:02:47
浏览器渲染机制页面之所以能渲染从服务器获取需要渲染的内容(URL解析/DNS/TCP/HTTP…)浏览器基于自己的渲染引擎(例如:webkit/gecko/trident/blink…)开始自上而下加载渲染代码服务器获取的是文件流浏览器首先把16进制的字节流信息编译为“代码字符串”按照w3c规则进行字符解析,生成对应的Tokens,最后转换为浏览器内核可以识别渲染的DOM节点按照节点最后解析为对应的树DOM树,CSSOM树,Render树浏览器在css资源还没有请求回来之前,先生...

浏览器渲染机制

页面之所以能渲染

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

服务器获取的是文件流

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

浏览器

  1. 在css资源还没有请求回来之前,先生成DOM树
  2. 当所有的css请求回来之后,浏览器按照css的导入顺序,依次进行渲染,最后生成cssom树
  3. 把DOM树和CSSOM树结合在一起,生成有样式,有结构的render树
  4. 浏览器按照渲染树,在页面中进行渲染和解析
  5. 计算元素在设备饰扣的大小和位置布局(layout)或重拍/回流(reflow)
  6. 根据渲染树以及回流得到的几何信息,得到节点的绝对像素=>绘制/重绘(painting)

link和@import都是导入外部样式(从服务器获取样式文件)

  1. 遇到link,浏览器会派出一个新的线程(HTTP线程)去加载资源文件,与此同时GUI渲染线程会继续向下渲染代码。不论css是否请求回来,代码都会继续渲染
  2. 遇到@import,GUI渲染线程会暂时停止渲染,去服务器加载资源文件,资源文件没有返回之前,是不会继续渲染的@import阻碍浏览器的渲染,项目中尽量少用
  3. 如果是style,GUI直接渲染

正常情况下js也会阻碍GUI的渲染

  1. js在一般在页面的底部,就是为了确保DOM树生成完才去加载js
  2. 可能会与defer和async异步管控js的请求

性能优化

  1. 减少DOM树渲染的时间(HTML层级不要太深,标签语义化…)
  2. 减少CSSOM树渲染时间(选择器是从右向左解析,所以尽可能减少选择器的层级【less/sass中的层级嵌套虽然好用,但是是一个大坑】)
  3. 减少HTTP的请求次数和请求大小
  4. 一般会把CSS放在页面的开始位置(提前请求资源 用link别用@import,对于移动端来讲,如果CSS比较少,尽可能采用内嵌式即可…)
  5. 为了避免白屏,可以进来第一件事,快速生成一套 loding 的渲染树(前端骨架屏);服务器的SSR骨架屏所提高的渲染是避免了客户端再次单独请求数据,而不是样式和结构上的(首屏处理)
  6. 把JS放在页面底部以及尽可能使用defer或者async
  7. CRP性能节点优化

DOM的重绘和回流Repaint和Reflow

  1. 重绘:元素样式的改变(但宽高、大小、位置不变)如:outline、visibility、color、background-color等
  2. 回流:元素的大小或者位置发生变化(当页面布局和几何信息发生变化的时候),触发了重新布局,导致渲染树重薪计算布局和渲染
  3. 如添加或删除可见的DOM元素;元素的位置发生变化;元素的尺寸发生变化(比如文本变化或图片被另一个不同尺寸的图片替代);页面一开始渲染的时候(这个无法避免);因为回流是根据视口大小来计算元素的位置和大小的,所以浏览器的窗口尺寸变化也会引发回流
  4. 回流一定会触发重绘,但是重绘不一定会回流

性能优化:避免DOM的回流

1、缓存布局信息
div.style.left = div.offsetLeft + 1 + ‘px’;
div.style.top = div.offsetTop + 1 + ‘px’;
修改为=>
var curLeft = div.offsetLeft;
var curTop = div.offsetTop;
div.style.left = curLeft + 1 + ‘px’;
div.style.top = curTop + 1 + ‘px’;

2、元素批量修改
文档碎片:createDocumentFragment
模板字符串拼接

3、动画效果应用position属性为absolute或fixed的元素上(脱离文档流)

4、CSS3硬件加速(GPU加速)
比起考虑如何减少回流重绘,我们更期望的是,根本不要回流重绘;transform/opacity/filters/这些属性会触发硬件加速,不会引发回流和重绘
可能会引发的坑:过多使用会占用大量内存,性能消耗严重,有时候会导致字体模糊等

5、牺牲平滑度换取速度
每次1像素移动一个动画,但是如果此动画使用了100%的CPU,动画就会看起来是跳动的,因为浏览器正在与更新回流做斗争,每次移动3像素可能看起来平滑度低了,但它不会导致cpu在比较慢的机器中抖动

6、避免table布局和使用css的JavaScript表达式

示例代码

	/* 点击盒子,让其立即回到0的位置,然后再运动到200的位置(动画1S) */
	<style>
	  .box {
	    position: absolute;
	    top: 100px;
	    left: 100px;
	    width: 100px;
	    height: 100px;
	    background: red;
	    transition: left 1s linear 0s;
	  }
	</style>

	// 现代版浏览器,两行修改操作,只引发一次回流
    // 浏览器的渲染队列机制:遇到修改样式的代码,浏览器没有立即渲染,而是先把他放到渲染队列中,继续看下面是否还是修改样式的,
    // 是的话继续放进去....(直到遇到获取元素样式的代码或者没有修改样式的代码了,则立即把队列中的样式统一进行渲染,最后只引发一次回流重绘)
	box.onclick = function () {
	  // 立即回到零
	  box.style.transitionDuration = '0s';
	  box.style.left = '0px';
	  // 运动到200的位置
	  box.style.transitionDuration = '1s';
	  box.style.left = '200px';
	};

	// 由于渲染队列机制原因,这样会触发两次,一旦遇到获取样式的代码,需要先把之前队列中的样式进行渲染
	box.onclick = function () {
	  box.style.transitionDuration = '0s';
	  box.style.left = '0px';
	  // 获取样式,会立即刷新渲染队列
	  box.offsetLeft;
	  box.style.transitionDuration = '1s';
	  box.style.left = '200px';
	};

	// 如果把2个操作放到宏任务中,也可以实现效果,但是两个宏任务的时间必须不一样,如果一样,那么还是会一起渲染的
	box.onclick = function () {
	  setTimeout(() => {
	    box.style.transitionDuration = '0s';
	    box.style.left = '0px';
	  }, 1)
	  setTimeout(() => {
	    box.style.transitionDuration = '1s';
	    box.style.left = '200px';
	  }, 2)
	};

	// 会同时渲染
	box.onclick = function () {
	  setTimeout(() => {
	    box.style.transitionDuration = '0s';
	    box.style.left = '0px';
	  })
	  setTimeout(() => {
	    box.style.transitionDuration = '1s';
	    box.style.left = '200px';
	  })
	};

	// 使用文档碎片
	let frg = document.createDocumentFragment();
	for (let i = 0; i < 10; i++) {
	  let span = document.createElement('span');
	  span.innerHTML = i;
	  frg.appendChild(span);
	}
	document.body.appendChild(frg);

本文地址:https://blog.csdn.net/uperficialyu/article/details/107246021