浏览器渲染揭秘:从加载到显示的全过程;浏览器工作原理与详细流程

简介: 了解浏览器工作原理与流程,能有效帮助前端开发与性能优化。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~


浏览器工作原理与流程

一、渲染开始时间点

       用户访问页面的时候,浏览器网络线程进行网络通信获取HTML代码,然后进入渲染主线程的消息队列进行包装,得到渲染任务后按需交由渲染主线程进行渲染。

image.gif 编辑

二、渲染主线程的渲染流程

2.1、渲染流程总览

       总流程如下图所示:

image.gif 编辑

2.2、渲染具体步骤

①解析html-Parse HTML

       该步骤主要生成DOM树和CSSOM树。html代码解析后生成DOM树,css代码解析后生成CSSOM树。

image.gif 编辑

       在解析过程中,为了提⾼解析效率,浏览器会启动⼀个预解析器率先下载和解析 CSS。

image.gif 编辑

       渲染主线程遇到 JS 时必须暂停⼀切⾏为,等待下载执⾏完后才能继续,预解析线程可以分担⼀点下载 JS 的任务,这里主要是因为JS可能会改变DOM树, 所以需要先解析,但如果声明是异步加载,那就不会暂停。

image.gif 编辑

②样式计算-Recalculate Style

       样式计算的目的是将HTML解析获得的DOM树和CSSOM树对应起来,只有DOM与CSSOM对应起来才能进行布局,为后面生成布局树奠定基础。

       有一种说法将DOM树与CSSOM树绑定后的树称为“渲染树”。笔者个人认为在布局树还没生成之前,叫它为渲染树有些过早了。

image.gif 编辑

③布局-Layout

       根据计算好的样式来生成布局树。布局树包含了之后渲染后呈现给我们的所有信息。

image.gif 编辑

       这里有一个误区,就是认为布局情况依赖DOM元素,所以布局树和DOM树应该是一一对应的。

       这句话是错误的,只能说布局树和可见内容是一一对应的,但是和DOM树并不一定一一对应。反例包括:

       1、display值为none的元素,只是不可见,但是依然会添加到DOM树中,而布局树中不会添加该元素。

image.gif 编辑

        2、before伪类添加的元素,由于不算做一个单独的元素,所以不会添加到DOM树中,但是会在布局中显示,所以会添加到布局树中。

image.gif 编辑

       3、浏览器在渲染过程中为了保持布局的连贯性和符合CSS规范会自动创建一些布局盒子:匿名行盒与匿名块盒,它们只会在布局树中添加,而不会影响DOM树。

image.gif 编辑

④分层-Layer

       在现代浏览器中,为了优化渲染性能,渲染树会被分解成多个层(Layers)。每个层可以独立于其他层进行渲染和合成,这有助于减少绘制和合成的工作量。

image.gif 编辑

       跟堆叠上下文有关的属性,会影响分层,比如z-index,opacity、transform、filter,或者元素被设置为will-change,以及部分动画和过度效果可能也会被分为新的层。

相关拓展

       opacity属性与堆叠上下文有关,因为当元素的opacity值小于1时,它将创建一个内部的堆叠上下文。这意味着,即使元素的z-index值较低,它的不透明部分仍然可以覆盖在其后面的元素的不透明部分。这可能导致一些不可预见的层叠效果,因为元素的不透明度会影响其在堆叠上下文中的行为。

       例如,假设有两个元素A和B,A在B的上方,A的z-index值较高,但A的opacity为0.5,B的opacity为1。在这种情况下,A的不透明部分将覆盖B,但A的半透明部分将允许B的内容显示出来。这是因为A的半透明部分创建了一个内部堆叠上下文,而B的内容在这个内部堆叠上下文中显示。

       堆叠上下文的层级规则如下:

  • 根元素(通常是HTML元素)形成一个堆叠上下文。
  • 定位元素(position属性为relative、absolute或fixed)可以形成新的堆叠上下文。
  • 元素的z-index属性可以指定其在堆叠上下文中的层级。
  • 某些CSS属性和值,如opacity、transform、filter等,可以创建新的堆叠上下文。

⑤绘制-Paint

       为分层结果的每⼀层⽣成如何绘制的指令,并不是真的绘制。

       到这里渲染主线程的工作就结束了,剩下的任务交给其他线程完成。

⑥分块-Tiling

       这一步会将每⼀层分为多个小的区域。分块的目的是对分层结果进行进一步细分,通过只渲染用户可以看到的部分(即视口中的部分),浏览器可以更快地完成绘制工作。当用户滚动页面时,浏览器可以丢弃不在视口中的块,并重新绘制新进入视口的块。

       以此来减少内存使用,提高渲染效率,优化重绘制,改善滚动性能。

image.gif 编辑

⑦光栅化-Raster

       光栅化将分块后的每个块都绘制成位图,优先处理靠近视口的块,以此提高渲染效率。这一过程需要GPU加速。

       有些说法将⑤⑥⑦三个部分统一为一个步骤“绘制”,其实是一个道理,只是颗粒度不同。

⑧画-Draw(合成)

       合成线程计算出每个位图在屏幕上的位置,交给GPU进行最终呈现。

image.gif 编辑

⑨完整过程分工示意图

       完整过程的分工情况如图:

image.gif 编辑

三、衍生问题

3.1、什么是reflow?

       reflow 的本质就是重新计算 layout 树。

       用js修改样式,即修改cssom树,如果修改几何信息,就会修改dom。修改了几何信息就会导致reflow(改变可见dom的结构、修改宽高等)

       reflow本身是异步请求,但是如果js中需要读取dom信息如dom.clientWidth,就会立即reflow来保证读取的信息是修改后的dom信息。

3.2、什么是repaint

       repaint 的本质就是重新根据分层信息计算了绘制指令。

       当改动了可见样式后,就需要重新计算,会引发 repaint。

       由于元素的布局信息也属于可见样式,所以 reflow 一定会引起 repaint。

3.3、为什么transform效率高

       因为 transform 既不会影响布局也不会影响绘制指令,它影响的只是渲染流程的最后一个「draw」阶段

       由于 draw 阶段在合成线程中,所以 transform 的变化几乎不会影响渲染主线程。反之,渲染主线程无论如何忙碌,也不会影响 transform 的变化。

四、总结与相关资源

       了解浏览器工作原理与流程,能有效帮助前端开发与性能优化。

       博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

        更多优质内容,请关注:

JS语法与Vue开发:

       Vue 性能革命:揭秘前端优化的终极技巧

       属性描述符初探——Vue实现数据劫持的基础

       你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

       最细最有条理解析:事件循环(消息循环)是什么?进程与线程的定义、关系与差异

       路由通配符,小小的字符有大大的作用,你真的熟悉吗?

       管理数据必备!侦听器watch用法详解

       什么是深拷贝?深拷贝和浅拷贝有什么区别

       对象数据的读取,看这一篇就够了!

       通过array.every()实现数据验证、权限检查和一致性检查,array.some与array.every的区别

       通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理

       通过array.map()实现数据转换、创建派生数组、异步数据流处理、搜索和过滤等需求

       通过array.reduce()实现数据汇总、条件筛选和映射、对象属性的扁平化、转换数据格式等

       通过array.filter()实现数组的数据筛选、数据清洗和链式调用

       多维数组操作,不要再用遍历循环foreach了,来试试数组展平的小妙招!

       别再用双层遍历循环来做新旧数组对比,寻找新增元素了!

       shpfile转GeoJSON且控制转化精度;如何获取GeoJSON?GeoJson结构详解

       Mapbox添加行政区矢量图层、分级设色图层、自定义鼠标悬浮框、添加天地图底图等

Element plus拓展:

       通过el-tree自定义渲染网页版工作目录,实现鼠标悬浮显示完整名称等

       el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

       el-table中如何添加渐变色带、多色色带

目录
打赏
0
0
0
0
7
分享
相关文章
在资源加载优化中,如何利用浏览器缓存提升性能?
通过以上这些方法,可以有效地利用浏览器缓存来提升资源加载的性能,减少网络请求次数,提高用户体验和应用的响应速度。同时,需要根据具体的应用场景和资源特点进行灵活调整和优化,以达到最佳的效果。此外,随着技术的不断发展和变化,还需要持续关注和学习新的缓存优化方法和策略。
128 53
浏览器渲染过程中如何处理异步任务
在浏览器渲染过程中,异步任务通过事件循环机制处理。JS执行时,同步任务在主线程上执行,形成一个执行栈。异步任务则被推入任务队列中,待主线程空闲时按顺序调用,确保页面流畅渲染与响应。
宏任务和微任务在浏览器渲染过程中的执行顺序
宏任务和微任务是浏览器事件循环中的两种任务类型。宏任务包括整体代码块、setTimeout等,微任务有Promise.then、MutationObserver等。每个宏任务执行完毕后,会先执行完所有微任务,再进行下一轮渲染或执行下一个宏任务。
浏览器渲染
【10月更文挑战第28天】浏览器渲染涉及将HTML、CSS和JavaScript代码转换为可视网页,主要步骤包括:解析HTML构建DOM树、解析CSS构建CSSOM树、合并DOM与CSSOM生成渲染树、布局确定元素位置和尺寸、绘制元素到屏幕、合成图层形成最终图像。此过程不断优化以提升性能。
模板字符串和普通字符串在浏览器和 Node.js 中的性能表现是否一致?
综上所述,模板字符串和普通字符串在浏览器和 Node.js 中的性能表现既有相似之处,也有不同之处。在实际应用中,需要根据具体的场景和性能需求来选择使用哪种字符串处理方式,以达到最佳的性能和开发效率。
133 63
|
4月前
|
Moment.js库是如何处理不同浏览器的时间戳格式差异的?
总的来说,Moment.js 通过一系列的技术手段和策略,有效地处理了不同浏览器的时间戳格式差异,为开发者提供了一个稳定、可靠且易于使用的时间处理工具。
156 57
在浏览器执行js脚本的两种方式
【10月更文挑战第20天】本文介绍了在浏览器中执行HTTP请求的两种方式:`fetch`和`XMLHttpRequest`。`fetch`支持GET和POST请求,返回Promise对象,可以方便地处理异步操作。`XMLHttpRequest`则通过回调函数处理请求结果,适用于需要兼容旧浏览器的场景。文中还提供了具体的代码示例。
在浏览器执行js脚本的两种方式
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
784 1
前端大模型入门:Transformer.js 和 Xenova-引领浏览器端的机器学习变革
除了调用API接口使用Transformer技术,你是否想过在浏览器中运行大模型?Xenova团队推出的Transformer.js,基于JavaScript,让开发者能在浏览器中本地加载和执行预训练模型,无需依赖服务器。该库利用WebAssembly和WebGPU技术,大幅提升性能,尤其适合隐私保护、离线应用和低延迟交互场景。无论是NLP任务还是实时文本生成,Transformer.js都提供了强大支持,成为构建浏览器AI应用的核心工具。
1109 1

热门文章

最新文章