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

目录

浏览器工作原理与流程

一、渲染开始时间点

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

2.1、渲染流程总览

2.2、渲染具体步骤

①解析html-Parse HTML

②样式计算-Recalculate Style

③布局-Layout

④分层-Layer

相关拓展

⑤绘制-Paint

⑥分块-Tiling

⑦光栅化-Raster

⑧画-Draw(合成)

⑨完整过程分工示意图

三、衍生问题

3.1、什么是reflow?

3.2、什么是repaint

3.3、为什么transform效率高

四、总结与相关资源


浏览器工作原理与流程

一、渲染开始时间点

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

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

2.1、渲染流程总览

        总流程如下图所示:

2.2、渲染具体步骤

①解析html-Parse HTML

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

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

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


②样式计算-Recalculate Style

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

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

③布局-Layout

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

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

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

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

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

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

④分层-Layer

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

        跟堆叠上下文有关的属性,会影响分层,比如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

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

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

⑦光栅化-Raster

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

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

⑧画-Draw(合成)

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

⑨完整过程分工示意图

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

三、衍生问题

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中如何添加渐变色带、多色色带

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/49049.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬虫 instagram API获取instagram帖子数据信息

这个instagram接口可以通过url链接直接获取相关帖子信息。如有需求,可点击文末链接联系我们。 详细采集页面 https://www.instagram.com/p/CqIbCzYMi5C/ 请求参数 返回示例 { "__typename": "GraphSidecar", "accessibility_caption&qu…

Python和MATLAB网络尺度结构和幂律度大型图生成式模型算法

🎯要点 🎯算法随机图模型数学概率 | 🎯图预期度序列数学定义 | 🎯生成具有任意指数的大型幂律网络,数学计算幂律指数和平均度 | 🎯随机图分析中巨型连接分量数学理论和推论 | 🎯生成式多层网络…

购物车案例(源码分享)

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

排序算法与复杂度介绍

1. 排序算法 1.1 排序算法介绍 排序也成排序算法(Sort Algorithm),排序是将一组数据,依照指定的顺序进行排序的过程 1.2 排序的分类 1、内部排序: 指将需要处理的所有数据都加载到**内部存储器(内存&am…

android13禁用某个usb设备

总纲 android13 rom 开发总纲说明 目录 1.前言 2.触摸设备查看 3.功能修改 3.1 禁用usb触摸 3.2 禁用usb键盘 3.3 禁用usb遥感 4.查看生效与否 5.彩蛋 1.前言 用户想要禁止使用某些usb设备,需要系统不能使用相关的usb设备,例如usb触摸屏,usb键盘,usb遥感等等usb…

Python零基础快速入门!

“人生苦短,我学python”是编程届的名言。用python写小脚本的便捷性,让很多其他语言的学习者把python当作辅助语言。拥有了某一个语言的功底,再来学习另外一种语言应该是十分快速的。编程理念都十分相似,只是看看语言的差异性。带…

Python函数的介绍;变量的作用域;递归函数

一、函数的创建和调用 1.1、什么是函数 函数就是执行特定任和以完成特定功能的一段代码 1.2、为什么需要函数 复用代码 隐藏实现细节 提高可维护性 提高可读性便于调试 1.3、函数的创建 def 函数名(输入函数)函数体(return XXX) 1.4、函数的调用 函数名 (实际参数) 二、…

当当网数据采集:Scrapy框架的异步处理能力

在互联网数据采集领域,Scrapy框架以其强大的异步处理能力而著称。Scrapy利用了Python的异步网络请求库,如twisted,来实现高效的并发数据采集。本文将深入探讨Scrapy框架的异步处理能力,并展示如何在当当网数据采集项目中应用这一能…

用Java手写jvm之实现java -version的效果

写在前面 源码 。 本文来用纯纯的Java代码来实现java -version的效果,就像下面这样: 1:程序 这里输出类似这样的: java version "9" Java(TM) SE Runtime Environment (build 9181) Java HotSpot(TM) 64-Bit Serve…

[保姆级教程]uniapp安装使用uViewUI教程

文章目录 创建 UniApp 项目下载uView UI下载安装方式步骤 1: 安装 uView UI步骤 2: 查看uView UI是否下载成功步骤 3: 引入 uView 主 JS 库步骤 4: 引入 uView 的全局 SCSS 主题文件步骤 5: 引入 uView 基础样式步骤 6: 配置 easycom 组件模式注意事项 NPM方式步骤 1: 安装 uVi…

websocket状态机

websocket突破了HTTP协议单向性的缺陷,基于HTTP协议构建了双向通信的通道,使服务端可以主动推送数据到前端,解决了前端不断轮询后台才能获取后端数据的问题,所以在小程序和H5应用中被广泛使用。本文主要集合报文分析对于websocket…

MATLAB绘制正弦波、余弦波、方波、三角波

一、引言 MATLAB是一种具有很强的数值计算和数据可视化软件,提供了许多内置函数来简化数学运算和图形的快速生成。在MATLAB中,你可以使用多种方法来快速绘制正弦波、方波和三角波。以下是一些基本的示例,展示了如何使用MATLAB的命令来实现正弦…

基于dcm4chee搭建的PACS系统讲解(一)docker搭建精简版

文章目录 知识点PACSdcm4chedcm4chee部署dcm4chee方式 docker部署docker编排 总结 最近项目开始需要用到PACS系统,于是研究了一番,选用了dcm4chee搭建PACS系统,抛出 dcm-arc-light的git地址 。 知识点 PACS Picture Archiving and Communic…

【详细的springboot自动装载原理】

1.默认提供的核心配置模块 springboot提供了 spring-boot-autoconfigure模块,该模块为springboot自动配置的核心模块,它初始化好了很多我们平时需要的配置类,那么有了这些配置类就能生效了吗?得需要一个东西在启动的时候去把它加…

uniapp 小程序 嵌套 webview 返回需要点击两次

uniapp 小程序 嵌套 webview 返回需要点击两次 先 上图 小程序也监听不到 返回事件在网上找了一圈 都没有理想的答案&#xff0c;猜测 是因为嵌入的页面中有问题果然 小程序中嵌入的代码 <view><web-view :src"urlSrc" ></web-view></view>…

jdk1.8 List集合Stream流式处理

jdk1.8 List集合Stream流式处理 一、介绍(为什么需要流Stream&#xff0c;能解决什么问题&#xff1f;)1.1 什么是 Stream&#xff1f;1.2 常见的创建Stream方法1.3 常见的中间操作1.4 常见的终端操作 二、创建流Stream2.1 Collection的.stream()方法2.2 数组创建流2.3 静态工厂…

理解进程status的二进制位表示及进程等待(是什么,为什么,怎么办)

信号编号&#xff1a;低7位 状态编号&#xff1a;次低8位 1.子进程退出后会变为僵尸进程&#xff0c;将退出结果写入自身的task_struct结构体中 2.wait/waitpid是一个系统调用->OS可以读取子进程的task_struct 1.为什么要进行进程等待&#xff1f; 1.将子进程&#xff…

C语言 | Leetcode C语言题解之第241题为运算表达式设计优先级

题目&#xff1a; 题解&#xff1a; #define ADDITION -1 #define SUBTRACTION -2 #define MULTIPLICATION -3int* diffWaysToCompute(char * expression, int* returnSize) {int len strlen(expression);int *ops (int *)malloc(sizeof(int) * len);int opsSize 0;for (in…

单周期CPU(三)译码模块(minisys)(verilog)(vivado)

timescale 1ns / 1ps //module Idecode32 (input reset,input clock,output [31:0] read_data_1, // 输出的第一操作数output [31:0] read_data_2, // 输出的第二操作数input [31:0] Instruction, // 取指单元来的指令input [31:0] …

前台文本直接取数据库值doFieldSQL插入SQL

实现功能&#xff1a;根据选择的车间主任带出角色。 实现步骤&#xff1a;OA的“字段联动”功能下拉选项带不出表“hrmrolemembers”&#xff0c;所以采用此方法。 doFieldSQL("select roleid from HrmResource as a inner join hrmrolemembers as b on a.id b.resource…