深入浏览器渲染原理

总览


🤡大家好,我是一溪风月一名前端工程师,做前端两年多了,但是自己反思了一下,在这两年多的时间,在对技术的追寻上一致都是追求在这个道路上往往忽略了前端最本质的东西,那就是前端究竟在做什么,前端的价值和意义在什么地方,前端的基础,经过自己的思考决定从头学习下前端的知识,让自己沉下心来查漏补缺,放弃追逐新东西,寻找自己,了解自己。

一.网页的解析过程


🐳网页下载静态资源的过程:在浏览器栏中输入URL,经过DNS服务器的解析也就是域名解析,通过域名解析将URL转为IP地址,通过IP地址访问服务器的资源,服务器返回前端的静态资源(HTML文件),浏览器通过HTML文件获取其他CSS文件和JavaScript文件进行解析,通过HTML的链接比如通过link链接获取CSS静态文件,通过script获取网页的JavaScript文件链接,遇到图片的资源,对应的去下载图片资源,然后进行展示。

二.浏览器内核


🤡Trident ( 三叉戟):IE、360安全浏览器、搜狗高速浏览器、百度浏览器、UC浏览器

😭Gecko( 壁虎) :Mozilla Firefox

📆Presto(急板乐曲)-> Blink (眨眼):Opera

🧙Webkit :Safari、360极速浏览器、搜狗高速浏览器、移动端浏览器(Android、iOS)

🥴Webkit -> Blink :Google Chrome,Edge

二.渲染页面的详细流程


🧙HTML解析过程:在默认情况下,服务器会给服务器默认返回index.html文件,所以解析都是从HTML开始的,解析HTML会创建DOM Tree

👽生成CSS规则:在解析过程中如果遇到CSS的link元素,那么浏览器会负责下载对应的CSS文件,并且CSS的下载是不会影响DOM Tree的构建的,浏览器下载完CSS后就会对CSS进行解析,解析出相应的规则树我们可以称之为CSSOM

😶‍🌫️Render Tree:当有了DOM TreeCSSOM后,就可以两个结合起来构建Render Tree了,link元素不会阻塞DOM Tree的构建过程,但是会阻塞Render Tree的构建过程,这是因为Render Tree载构建的时候,需要对应的CSSOM TreeRender TreeDOM Tree并不是一一对应的关系,比如对于displaynone的元素压根不会出现在Render Tree中。

🎯布局与绘制:第四步是在渲染树(Render Tree)上运行布局(Layout)以计算每个节点的几何体,渲染树会表示显示哪些节点以及其他样式,但是不表示每个节点的尺寸、位置等信息;布局是确定呈现树中所有节点的宽度,高度和位置信息,第五步是将每个节点绘制(Paint)到屏幕上,在绘制阶段,浏览器将布局阶段计算的每个frame转为屏幕上实际的像素点,包括将元素的可见部分进行绘制,比如文本,颜色,边框,阴影,替换元素。

三.回流和重绘


🐳理解回流reflow:(也可以称之为重排)第一次确定节点的大小和位置,称之为布局,之后对节点的大小、位置修改重新计算称之为回流。

🤡什么情况下会引起回流哪?

  1. 比如DOM结构发生改变(添加新的节点或者移除节点)
  2. 比如改变了布局(修改了width、height、padding、font-size等值)
  3. 比如窗口resize(修改了窗口的尺寸等)
  4. 比如调用getComputedStyle方法获取尺寸、位置信息;

😭理解重绘repaint:第一次渲染内容称之为绘制,之后重新渲染称之为重绘。

😊什么情况下会引起重绘呢?比如修改背景色、文字颜色、边框颜色、样式等。

🚨注意:回流一定会引起重绘,所以回流是一件很消耗性能的事情,所以在开发中要尽量避免发生回流:

  1. 修改样式时尽量一次性修改,比如通过cssText修改,比如通过添加class修改。
  2. 尽量避免频繁的操作DOM,我们可以在一个DocumentFragment或者父元素中将要操作的DOM操作完成,再一次性的操作。
  3. 尽量避免通过getComputedStyle获取尺寸、位置等信息。
  4. 对某些元素使用position的absolute或者fixed并不是不会引起回流,而是开销相对较小,不会对其他元素造成影响。

四.特殊解析-composite合成


🥴绘制的过程,可以将布局后的元素绘制到多个合成图层中,这是浏览器的一种优化手段,默认情况下,标准流中的内容都是被绘制在同一个图层(Layer)中的,而一些特殊的属性,会创建一个新的合成层( CompositingLayer ),并且新的图层可以利用GPU来加速绘制,因为每个合成层都是单独渲染的,那么哪些属性可以形成新的合成层呢?常见的一些属性:

  1. 3D transforms
  2. video、canvas、iframe
  3. opacity 动画转换时;
  4. position: fixed
  5. will-change:一个实验性的属性,提前告诉浏览器元素可能发生哪些变化;
  6. animation 或 transition 设置了opacity、transform;
  7. 分层确实可以提高性能,但是它以内存管理为代价,不应作为 web 性能优化策略的一部分过度使用。

五.script元素和页面解析的关系


我们现在已经知道了页面的渲染过程,但是JavaScript在哪里呢?事实上,浏览器在解析HTML的过程中,遇到了script元素是不能继续构建DOM树的,它会停止继续构建,首先下载JavaScript代码,并且执行JavaScript的脚本,只有等到JavaScript脚本执行结束后,才会继续解析HTML,构建DOM树,为什么要这样做呢?这是因为JavaScript的作用之一就是操作DOM,并且可以修改DOM,如果我们等到DOM树构建完成并且渲染再执行JavaScript,会造成严重的回流和重绘,影响页面的性能,所以会在遇到script元素时,优先下载和执行JavaScript代码,再继续构建DOM树,但是这个也往往会带来新的问题,特别是现代页面开发中:在目前的开发模式中(比如Vue、React),脚本往往比HTML页面更"重",处理时间需要更长,所以会造成页面的解析阻塞,在脚本下载、执行完成之前,用户在界面上什么都看不到,为了解决这个问题,script元素给我们提供了两个属性(attribute):defer和async。

👽defer属性:defer 属性告诉浏览器不要等待脚本下载,而继续解析HTML,构建DOM Tree。

  1. 脚本会由浏览器来进行下载,但是不会阻塞DOM Tree的构建过程。

  2. 如果脚本下载好了它会等待DOM Tree构建完成,在DOMContentLoaded事件之前先执行defer中的代码这样做是因为defer下载的代码很可能会对DOM进行操作,如果在DOMContentLoaded事件之后会造成严重回流的情况,就像上述所说的那用,所以会之前这个时机进行执行。

  3. 所以DOMContentLoaded总是会等待defer中的代码先执行完成,另外多个带defer的脚本是可以保持正确的顺序执行的,从某种角度来说,defer可以提高页面的性能,并且推荐放到head元素中;

  1. 注意:defer仅适用于外部脚本,对于script默认内容会被忽略。

📆async属性:async 特性与 defer 有些类似,它也能够让脚本不阻塞页面,async是让一个脚本完全独立的,浏览器不会因 async 脚本而阻塞(与 defer 类似),async脚本不能保证顺序,它是独立下载、独立运行,不会等待其他脚本,async不会能保证在DOMContentLoaded之前或者之后执行。

🤡defer通常用于需要在文档解析后操作DOM的JavaScript代码,并且对多个script文件有顺序要求的;

🥴async通常用于独立的脚本,对其他脚本,甚至DOM没有依赖的;


相关推荐
大前端爱好者1 小时前
React 19 新特性详解
前端
随云6321 小时前
WebGL编程指南之着色器语言GLSL ES(入门GLSL ES这篇就够了)
前端·webgl
寻找09之夏2 小时前
【Vue3实战】:用导航守卫拦截未保存的编辑,提升用户体验
前端·vue.js
多多米10053 小时前
初学Vue(2)
前端·javascript·vue.js
柏箱3 小时前
PHP基本语法总结
开发语言·前端·html·php
新缸中之脑3 小时前
Llama 3.2 安卓手机安装教程
前端·人工智能·算法
hmz8563 小时前
最新网课搜题答案查询小程序源码/题库多接口微信小程序源码+自带流量主
前端·微信小程序·小程序
看到请催我学习3 小时前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript
blaizeer4 小时前
深入理解 CSS 浮动(Float):详尽指南
前端·css
编程老船长4 小时前
网页设计基础 第一讲:软件分类介绍、工具选择与课程概览
前端