浏览器的渲染原理简介

2023-11-16

http://cloudbbs.org/forum.php?mod=viewthread&tid=16940

浏览器的渲染原理简介 [复制链接]

   

Rank: 8Rank: 8

跳转到指定楼层
楼主
  发表于 昨天 15:48  | 只看该作者  | 倒序浏览

看到这个标题大家一定会想到这篇神文《How Browsers Work》,这篇文章把浏览器的很多细节讲得很细,而且也被翻译成了中文。为什么我还想写一篇呢?因为两个原因,

1)这篇文章太长了,阅读成本太大,不能一口气读完。

2)花了大力气读了这篇文章后可以了解很多,但似乎对工作没什么帮助。

所以,我准备写下这篇文章来解决上述两个问题。希望你能在上班途中,或是坐马桶时就能读完,并能从中学会一些能用在工作上的东西。


浏览器工作大流程


废话少说,先来看个图:


u.jpg



从上面这个图中,我们可以看到那么几个事:
1)浏览器会解析三个东西:

  • 一个是HTML/SVG/XHTML,事实上,Webkit有三个C++的类对应这三类文档。解析这三种文件会产生一个DOM Tree。

  • CSS,解析CSS会产生CSS规则树。

  • Javascript,脚本,主要是通过DOM API和CSSOM API来操作DOM Tree和CSS Rule Tree.

2)解析完成后,浏览器引擎会通过DOM Tree 和 CSS Rule Tree 来构造 Rendering Tree。注意:
  • Rendering Tree 渲染树并不等同于DOM树,因为一些像Header或display:none的东西就没必要放在渲染树中了。
  • CSS 的 Rule Tree主要是为了完成匹配并把CSS Rule附加上Rendering Tree上的每个Element。也就是DOM结点。也就是所谓的Frame。
  • 然后,计算每个Frame(也就是每个Element)的位置,这又叫layout和reflow过程。
3)最后通过调用操作系统Native GUI的API绘制。


DOM解析

HTML的DOM Tree解析如下:

HTML代码
<html>
<html>
<head>
    <title>Web page parsing</title>
</head>
<body>
    <div>
        <h1>Web page parsing</h1>
        <p>This is an example Web page.</p>
    </div>
</body>
</html>
上面这段HTML会解析成这样:




DOM-Tree-01.jpg 


下面是另一个有SVG标签的情况。


DOM-Tree-02.jpg 


CSS解析

CSS的解析大概是下面这个样子(下面主要说的是Gecko也就是Firefox的玩法),假设我们有下面的HTML文档:


HTML代码
<doc>
<title>A few quotes</title>
<para>
  Franklin said that <quote>"A penny saved is a penny earned."</quote>
</para>
<para>
  FDR said <quote>"We have nothing to fear but <span>fear itself.</span>"</quote>
</para>
</doc>

于是DOM Tree是这个样子:




3.jpg 



然后我们的CSS文档是这样的:


PHP代码
/* rule 1 */ doc { display: block; text-indent: 1em; }
/* rule 2 */ title { display: block; font-size: 3em; }
/* rule 3 */ para { display: block; }
/* rule 4 */ [class="emph"] { font-style: italic; }
于是我们的CSS Rule Tree会是这个样子:


4.jpg 


注意,图中的第4条规则出现了两次,一次是独立的,一次是在规则3的子结点。所以,我们可以知道,建立CSS Rule Tree是需要比照着DOM Tree来的。CSS匹配DOM Tree主要是从右到左解析CSS的Selector,好多人以为这个事会比较快,其实并不一定。关键还看我们的CSS的Selector怎么写了。

注意:CSS匹配HTML元素是一个相当复杂和有性能问题的事情。所以,你就会在N多地方看到很多人都告诉你,DOM树要小,CSS尽量用id和class,千万不要过渡层叠下去,……

通过这两个树,我们可以得到一个叫Style Context Tree,也就是下面这样(把CSS Rule结点Attach到DOM Tree上):



b1.jpg



所以,Firefox基本上来说是通过CSS 解析 生成 CSS Rule Tree,然后,通过比对DOM生成Style Context Tree,然后Firefox通过把Style Context Tree和其Render Tree(Frame Tree)关联上,就完成了。注意:Render Tree会把一些不可见的结点去除掉。而Firefox中所谓的Frame就是一个DOM结点,不要被其名字所迷惑了


Firefox-style-context-tree.png

注:Webkit不像Firefox要用两个树来干这个,Webkit也有Style对象,它直接把这个Style对象存在了相应的DOM结点上了。


 
   

Rank: 8Rank: 8

沙发
  发表于 昨天 15:48  | 只看该作者
本帖最后由 遇见sharon 于 2013-7-22 15:47 编辑

渲染

渲染的流程基本上如下(黄色的四个步骤):

1.计算CSS样式
2.构建Render Tree
3.Layout – 定位坐标和大小,是否换行,各种position, overflow, z-index属性 ……
4.正式开画

5.jpg 


注意:上图流程中有很多连接线,这表示了Javascript动态修改了DOM属性或是CSS属会导致重新Layout,有些改变不会,就是那些指到天上的箭头,比如,修改后的CSS rule没有被匹配到,等。这里重要要说两个概念,一个是Reflow,另一个是Repaint。这两个不是一回事。
  • Repaint——屏幕的一部分要重画,比如某个CSS的背景色变了。但是元素的几何尺寸没有变。
  • Reflow——意味着元件的几何尺寸变了,我们需要重新验证并计算Render Tree。是Render Tree的一部分或全部发生了变化。这就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的几何尺寸发生了变化,需要重新布局,也就叫reflow)reflow 会从<html>这个root frame开始递归往下,依次计算所有的结点几何尺寸和位置,在reflow过程中,可能会增加一些frame,比如一个文本字符串必需被包装起来。

下面是一个打开Wikipedia时的Layout/reflow的视频(注:HTML在初始化的时候也会做一次reflow,叫intial reflow),你可以感受一下:http://v.youku.com/v_show/id_XMzI5MDg0OTA0.html
eflow的成本比Repaint的成本高得多的多。DOM Tree里的每个结点都会有reflow方法,一个结点的reflow很有可能导致子结点,甚至父点以及同级结点的reflow。在一些高性能的电脑上也许还没什么,但是如果reflow发生在手机上,那么这个过程是非常痛苦和耗电的

所以,下面这些动作有很大可能会是成本比较高的。

  • 当你增加、删除、修改DOM结点时,会导致Reflow或Repaint
  • 当你移动DOM的位置,或是搞个动画的时候。
  • 当你修改CSS样式的时候。
  • 当你Resize窗口的时候(移动端没有这个问题),或是滚动的时候。
  • 当你修改网页的默认字体时。

注:display:none会触发reflow,而visibility:hidden只会触发repaint,因为没有发现位置变化。

多说两句关于滚屏的事,通常来说,如果在滚屏的时候,我们的页面上的所有的像素都会跟着滚动,那么性能上没什么问题,因为我们的显卡对于这种把全屏像素往上往下移的算法是很快。但是如果你有一个fixed的背景图,或是有些Element不跟着滚动,有些Elment是动画,那么这个滚动的动作对于浏览器来说会是相当相当痛苦的一个过程。你可以看到很多这样的网页在滚动的时候性能有多差。因为滚屏也有可能会造成reflow。


基本上来说,reflow有如下的几个原因:

  • Initial。网页初始化的时候。
  • Incremental。一些Javascript在操作DOM Tree时。
  • Resize。其些元件的尺寸变了。
  • StyleChange。如果CSS的属性发生变化了。
  • Dirty。几个Incremental的reflow发生在同一个frame的子树上。
好了,我们来看一个示例吧:
HTML代码 
  1. var bstyle = document.body.style; // cache
  2. bstyle.padding = "20px"; // reflow, repaint
  3. bstyle.border = "10px solid red"; //  再一次的 reflow 和 repaint
  4. bstyle.color = "blue"; // repaint
  5. bstyle.backgroundColor = "#fad"; // repaint
  6. bstyle.fontSize = "2em"; // reflow, repaint
  7. // new DOM element - reflow, repaint
  8. document.body.appendChild(document.createTextNode('dude!'));
当然,我们的浏览器是聪明的,它不会像上面那样,你每改一次样式,它就reflow或repaint一次。一般来说,浏览器会把这样的操作积攒一批,然后做一次reflow,这又叫异步reflow或增量异步reflow。但是有些情况浏览器是不会这么做的,比如:resize窗口,改变了页面默认的字体,等。对于这些操作,浏览器会马上进行reflow。但是有些时候,我们的脚本会阻止浏览器这么干,比如:如果我们请求下面的一些DOM值:
  • offsetTop, offsetLeft, offsetWidth, offsetHeight
  • scrollTop/Left/Width/Height
  • clientTop/Left/Width/Height
  • IE中的 getComputedStyle(), 或 currentStyle

因为,如果我们的程序需要这些值,那么浏览器需要返回最新的值,而这样一样会flush出去一些样式的改变,从而造成频繁的reflow/repaint。

减少reflow/repaint


下面是一些Best Practices:


1)不要一条一条地修改DOM的样式。与其这样,还不如预先定义好css的class,然后修改DOM的className。

HTML代码 
  1. // bad
  2. var left = 10,
  3. top = 10;
  4. el.style.left = left + "px";
  5. el.style.top  = top  + "px";
  6. // Good
  7. el.className += " theclassname";
  8. // Good
  9. el.style.cssText += "; left: " + left + "px; top: " + top + "px;";

2)把DOM离线后修改。如:使用documentFragment 对象在内存里操作DOM先把DOM给display:none(有一次reflow),然后你想怎么改就怎么改。比如修改100次,然后再把他显示出来。clone一个DOM结点到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。
3)不要把DOM结点的属性值放在一个循环里当成循环里的变量。不然这会导致大量地读写这个结点的属性。

4)尽可能的修改层级比较低的DOM。当然,改变层级比较底的DOM有可能会造成大面积的reflow,但是也可能影响范围很小。


5)为动画的HTML元件使用fixed或absoult的position,那么修改他们的CSS是不会reflow的。

6)千万不要使用table布局。因为可能很小的一个小改动会造成整个table的重新布局。

In this manner, the user agent can begin to lay out the table once the entire first row has been received. Cells in subsequent rows do not affect column widths. Any cell that has content that overflows uses the ‘overflow’ property to determine whether to clip the overflow content.

Fixed layout, CSS 2.1 Specification
This algorithm may be inefficient since it requires the user agent to have access to all the content in the table before determining the final layout and may demand more than one pass.

Automatic layout, CSS 2.1 Specification

 
 
   

Rank: 8Rank: 8

板凳
  发表于 昨天 15:48  | 只看该作者
本帖最后由 遇见sharon 于 2013-7-22 15:46 编辑

几个工具和几篇文章

有时候,你会也许会发现在IE下,你不知道你修改了什么东西,结果CPU一下子就上去了到100%,然后过了好几秒钟repaint/reflow才完成,这种事情以IE的年代时经常发生。所以,我们需要一些工具帮我们看看我们的代码里有没有什么不合适的东西。

  • Chrome下,Google的SpeedTracer是个非常强悍的工作让你看看你的浏览渲染的成本有多大。其实Safari和Chrome都可以使用开发者工具里的一个Timeline的东东。
  • IE下你可以用一个叫dynaTrace的IE扩展。

最后,别忘了下面这几篇提高浏览器性能的文章:




参考


via 酷壳 – CoolShell.cn




 
 
   

Rank: 1

地板
  发表于 1 小时前  | 只看该作者
 说的漂亮~~~~
 
 
   

Rank: 1

5#
  发表于 27 分钟前  | 只看该作者
之前在酷shell挺火的一篇文章
 
 
   

Rank: 1

6#
  发表于 11 分钟前  | 只看该作者
做个标志,mark
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浏览器的渲染原理简介 的相关文章

  • xmlHttpRequest的status的值的含义

    转自 http www cnblogs com zhubaoxu archive 2008 03 17 1109315 html 虽然常写ajax方面的东西 但是很少去专门了解xmlHttpRequest的status各个值的含义 只是在用
  • 会话跟踪技术:会话Cookie,URL重写和HttpSession

    一 会话跟踪 session tracking 技术 会话是客户端发送请求 服务器返回响应的连接时间段 HTTP是无状态协议 每次都是单独连接 不能维持客户的上下文信息 会话跟踪技术是用于维持客户端和服务器端通信信息的技术 三种典型客户端会
  • ASP快速入门教程

    ASP快速入门教程 ASP快速入门教程能让你一个小时就学会ASP 如果想看懂更多的ASP代码 希望大家在网上找找ASP教程 相信看完后大家对ASP更有个感性的认识 请熟记下面的ASP语句是你快速入门的不二法则 lt 1 gt lt 2 gt
  • 在线观看北京奥运会直播 在网上看奥运会直播

    2008年北京奥运会开幕明天就来了 本次奥运会的赛事大多是在白天进行的 虽然CCTV拿出7个频道为本次奥运直播 但是对于大多数上班族 白天的 上班时间通过电视来看奥运直播是不太可能的 还好现在有网络直播 只要可以上网 就可以第一时间在线观看
  • HTTP中Put和Post的区别

    解释HTTP中Put和Post 它们有什么区别 哪个使用时更加安全 Put和Post都是浏览器向网页服务器提交数据的方法 Put把要提交的数据编码在url中 比如 http hi baidu com mianshiti key1 value
  • 浏览器的事件轮询(消息轮询)

    目录 浏览器的进程模型 何为进程 何为线程 浏览器有哪些进程和线程 渲染主线程是如何 作的 相关问题 何谓异步 JS为什么会阻塞渲染 JS 中的计时器为什么无法精确计时 任务队列与优先级 浏览器的进程模型 何为进程 程序运 需要有它 专属的
  • Java Servlet的主要功能和作用是什么?

    Servlet 通过创建一个框架来扩展服务器的能力 以提供在 Web 上进行请求和响应服务 当客户机发送请求至服务器时 服务器可以将请求信息发送给 Servlet 并让 Servlet 建立起服务器返回给客户机的响应 当启动 Web 服务器
  • chrome插件使用整理

    1 postman 功能 模拟网页调试与发送网页HTTP请求 安装 进入chrome网上应用商店 搜索postman 点击添加至chrome 装好后 启用即可 使用 具体如下图 设置完请求 发送即可 总结 构建请求方便 对于调试API 以及
  • 多益网络校招笔试题(前端工程师)

    1 写出inline和inline block的差别 布局方式相同 唯一的区别在inline block可以设置宽高 inline不可以 另外 inline设置上下内边距和上下外边距会造成一些mess 详见 What is the diff
  • 如何删除文件夹右键菜单多余项

    如何删除文件夹右键菜单多余项 1 所有或大部分文件都有的右键菜单 打开注册表编辑器后 在 HKEY CLASSES ROOT Shellex ContextMenuHandlers 根据名称删除相应的子项 2 文件夹的右键菜单 在注册表中的
  • H5 iOS 微信内核软键盘收起,页面不下滑问题解决(微信开发直播间踩坑记 一)

    网上搜了好多下面这段代码完美的解决了我的问题 input textarea on blur function window scroll 0 0 select on change function window scroll 0 0 原理就
  • TD添加IE8支持

    今天同事突然安装了IE8了 说TestDirector8 0在IE8 0下无法使用 于是在网上搜索 最后终于知道解决方法了 方法一 下载插件 安装TD自带的浏览器 通用 使用 进入TestDirector 单击Add ins Page 在新
  • (转)提高网站速度的最佳实践

    原文来自 http www space007 com post 129 html 相信互联网已经越来越成为人们生活中不可或缺的一部分 ajax flex等等富客户端的应用使得人们越加 幸福 地体验着许多原先只能在C S实现的功能 比如Goo
  • 开发浏览器扩展程序(js脚本)

    一 打开谷歌浏览器扩展程序 二 打开 开发者模式 三 加载已解压的扩展程序 四 选择编写好的脚本文件夹 看不到文件 没关系 默认会加载 manifest json 文件 实际文件夹内容 五 加载成功 六 开始编辑脚本文件 name 扩展名字
  • 浏览器打开就是360导航(浏览器被360劫持)

    浏览器打开就是360导航 这个问题之前只是看别人帖子见到过 不知道出了什么问题我的edge和Chrome浏览器突然打开也成了360的导航页面 这才感觉出这个问题的恶心之处 而且顺道说一下 我电脑中也没有装任何360系的应用 但突然就被改了
  • 修复ie浏览器主页被360篡改

    一 环境 win10 二 问题 打开ie浏览器 发现主页被360篡改了 360我没有装过 怀疑是其他软件修改的 分析 浏览器主页被篡改 一般都是注册表被修改了 或者是启动程序里面有加载篡改主页 首先 看是否启动程序里面有加载篡改了主页 用右
  • 如何把IE浏览器快速变成灰色来哀悼在汶川地震中遇难的同胞们!

    如何把IE浏览器快速变成灰色来哀悼在汶川地震中遇难的同胞们 把IE浏览器快速变成灰色只要作以下二点即可 第一点 在html页面中 在body中加入下面语句 第二点 在css控制表中 加入下面语句 html filter progid DXI
  • 步步学ACTIVEX网页控件开发

    本文将首先介绍如何使用Visual Studio开发一个简单的ActiveX控件 然后介绍ActiveX控件开发相关的基础知识 比如方法 属性和事件等 最后介绍如何利用这些知识 实现ActiveX控件和网页页面之间的 通信 MyActive
  • 浏览器原理篇—渲染原理

    目录导航 为什么要学习浏览器的渲染原理 浏览器的渲染流程 浏览器的渲染阻塞 浏览器的渲染优化 为什么要学习浏览器的渲染原理 知识深度挖掘 帮助更好地理解前端性能优化 从而对实现效果进行针对性优化 如 回流和重绘 渲染机制 帮助更好地理解浏览
  • 浏览器原理篇—渲染原理

    目录导航 为什么要学习浏览器的渲染原理 浏览器的渲染流程 浏览器的渲染阻塞 浏览器的渲染优化 为什么要学习浏览器的渲染原理 知识深度挖掘 帮助更好地理解前端性能优化 从而对实现效果进行针对性优化 如 回流和重绘 渲染机制 帮助更好地理解浏览

随机推荐

  • trading view实现

    TradingView udf模式 近期k线更新 刚趟完坑 简单总结一下 第一步 申请tv 官网地址 https cn tradingview com 注 需以公司名义申请 第二步 相关资料 文档 https b aitrade ga bo
  • 特殊乘法。。

    题目描述 写个算法 对两个小于1000000000的输入 求特殊乘法的结果 特殊乘法举例 123 45 1 4 1 5 2 4 2 5 3 4 3 5 输入 两个小于1000000000的数 输出 输入可能有多组数据 对于每组数据 Inpu
  • vue学习笔记3——外部引入css和路由的一部分

    vue学习笔记3 外部引入css和路由的一部分 从外部引入css文件 在 vue文件中 后面加的scoped是H5新特性 可以锁定style的范围 此处这样写就是说引入的css只在当前的vue的主页生效 不加scoped的话 可能会影响其他
  • Hadoop的伪分布式的安装及部署

    文章目录 需要的软件及源码包 安装JDK Hadoop的部署安装 Hadoop的配置 Hadoop的使用 做Hadoop的伪分布式我们分为一下几个步骤
  • [SQL Server]从数据类型 nvarchar 转换为 numeric 时出错。 (8114)

    SQL Server 从数据类型 nvarchar 转换为 numeric 时出错 8114 解决方法 SELECT FROM TABLENAME L where TRY CONVERT decimal 18 2 COLUNNAME is
  • 2023高教社杯 国赛数学建模C题思路 - 蔬菜类商品的自动定价与补货决策

    1 赛题 在生鲜商超中 一般蔬菜类商品的保鲜期都比较短 且品相随销售时间的增加而变差 大部分品种如当日未售出 隔日就无法再售 因此 商超通常会根据各商品的历史销售和需 求情况每天进行补货 由于商超销售的蔬菜品种众多 产地不尽相同 而蔬菜的进
  • Leetcode[数组] 买卖股票的最佳时机 -- 动态规划

    0 题目描述 leetcode原题链接 买卖股票的最佳时机 1 动态规划 假设给定的数组为 7 1 5 3 6 4 如果我们在图表上绘制给定数组中的数字 我们将会得到 我们来假设自己来购买股票 随着时间的推移 每天我们都可以选择出售股票与否
  • pycharm快速注释快捷键

    1 多行注释 用鼠标选中需要注释的代码 三次按下 shift 即可快速注释 2 单行注释 选中该行 按下 ctrl 即可单行注释
  • 【LeetCode】MySQL:数据库简单题(586 订单最多的客户)

    586 订单最多的客户 1 题目描述 2 具体实现 Write your MySQL query statement below 为下了最多订单的客户查找customer number 分组 排序 Limit select customer
  • 使用BiseNet从头训练&&微调自己的数据集

    一 代码链接 本次训练采用的是pytorch版本的BiseNet 代码链接为GitHub CoinCheung BiSeNet Add bisenetv2 My implementation of BiSeNet 二 数据格式 数据集分为原
  • Linux下安装Git

    文章目录 一 Git 安装 1 下载Git安装包 2 将Git安装包上传到服务器 3 解压Git安装包 4 安装Git所需依赖 5 编译与安装Git 6 设置环境变量 7 执行profile文件 使配置立即生效 一 Git 安装 如果觉得下
  • 笔记:几个基本数据结构——Ndarray、Series和Dataframe

    目录 一 Ndarray 1 创建 1 直接使用 np array创建 2 使用NumPy中函数 array func lt gt 2 索引 1 一维数组 array start end step 2 多维数组 3 基本操作 运算 操作 如
  • idea配置备份到GitHub

    目录 普通导入导出到本地 备份到GitHub 普通导入导出到本地 备份 File gt Export Settings 恢复 File gt Import Settings 2020版本 自定义Intellij idea配置和插件存放目录
  • CTP 穿透测试程序

    CTP穿透测试程序 修改配置文件后即可进行运行测试 方便简单 https download csdn net download someonemt5 11215587
  • redis开启过期监听

    java项目中 场景 订单没有付款到期取消订单 使用的是redis过期监听来做的 做个笔记 首先使用该功能需要下载2 8 0及以上的版本 这一部分详细内容可以访问redis官网 http redis io topics notificati
  • Rsync命令参数以及配置使用

    原文链接 参考原文笔记 https www cnblogs com koushuige p 9162920 html https www cnblogs com koushuige p 9162895 html https www cnbl
  • HttpRunner--自定义输出报告

    httprunner版本 2 5 4 jinja2版本 2 11 httprunner输出的html测试报告 默认的模板文件的路劲为 python安装路径 Lib site packages httprunner templates rep
  • 阻止冒泡(例:a标签上面绝对定位的文字标签【×】

    如何阻止冒泡 直接上图 js如下
  • python+selenium+实战(6)

    web 自动化脚本生成方式 1 selenium IDE 直接录屏 录制完成生成脚本 缺点 容易产生很多错误 解决错误的时间成本太高 2 自己写 remote复用已有浏览器 相当于开启浏览器调试模式 1 配置复用浏览器 注意要关闭浏览器 包
  • 浏览器的渲染原理简介

    http cloudbbs org forum php mod viewthread tid 16940 浏览器的渲染原理简介 复制链接 遇见sharon 超级版主 串个门 加好友 打招呼 发消息 电梯直达 楼主 发表于 昨天 15 48