已合作成功的客户

遍及全国及海外

中国

杭州,绍兴,宁波,湖州,嘉兴,温州,台州,上海,北京,南京,苏州,常州,无锡,长沙,青岛,江西,台湾,南宁,海南,成都,哈尔滨,深圳,香港,沈阳 ...

海外

美国,加拿大,丹麦,澳大利亚,新加坡,法国,智利,日本,英国 ...

合作咨询

4001-355-360

洞见

news

洞察行业新闻,实时了解最新动态

从地址栏到像素:浏览器渲染的隐藏逻辑

作者:admin

来源:lanyunwork

时间:2025-12-16

分享到:

当你打开浏览器,输入网址,按下回车,一个多彩的网页瞬间呈现在眼前。这看似简单的过程背后,隐藏着一套复杂而精密的渲染逻辑。从接收字节流到最终在屏幕上绘制像素,浏览器完成了一场无声的技术交响乐。

第一阶段:构建DOM树 - 从字节到结构

浏览器收到HTML文档后,渲染引擎的第一项任务是将原始字节转换为有意义的字符,再将这些字符解析成标记(token),最终构建出文档对象模型(DOM)树

<!-- 原始HTML -->
<html>
  <body>
    <div class="container">
      <h1>标题</h1>
      <p>段落内容</p>
    </div>
  </body>
</html>

上述代码将被转换为树形结构,其中每个HTML元素成为一个节点,元素间的关系形成父子层级。这个过程不是一蹴而就的——浏览器采用增量方式构建DOM,以便在接收到部分内容时就能开始后续处理,这也是为什么我们有时会看到网页逐步加载。

但DOM构建并非总是一帆风顺。当解析器遇到<script>标签时,它会暂停DOM构建,下载(如果是外部脚本)并执行JavaScript代码。这是因为JavaScript可能会通过document.write()或DOM操作改变文档结构。现代浏览器通过预加载扫描器缓解这一问题,它会在主解析器工作时提前寻找并下载关键资源。

第二阶段:样式计算 - 确定每个元素的视觉表现

仅有DOM树还不足以确定元素如何显示。浏览器需要结合CSS规则,为每个DOM节点计算最终样式。

这一过程包括多个步骤:

  1. 收集样式来源:浏览器收集所有样式表(外部、内部、行内)、浏览器默认样式和用户自定义样式

  2. 标准化值:将emrem百分比等相对单位转换为绝对像素值

  3. 计算层叠值:根据CSS层叠规则(特异性、重要性、来源顺序)确定每个属性的最终值

/* 外部样式表 */
.container { width: 80%; }

/* 内部样式 */
div { width: 50% !important; }

/* 浏览器将根据特异性规则确定最终应用的宽度值 */

有趣的是,现代浏览器采用了一种称为“样式共享”的优化技术:当检测到多个元素具有完全相同的计算样式时,它们会共享同一个样式对象,显著减少内存占用。

第三阶段:布局(重排)- 计算几何位置

有了带样式的DOM树,浏览器现在需要计算每个元素在视口中的确切位置和尺寸,这个过程称为布局重排

布局引擎会遍历渲染树(DOM树+样式信息),根据盒模型计算每个元素的几何属性:

布局是一个递归过程,从根元素开始,逐步确定所有后代元素的位置。某些CSS属性(如floatposition: absolute)会创建新的布局上下文,影响计算方式。

重排代价高昂:当JavaScript修改了元素的几何属性(如宽度、位置)或内容时,浏览器需要重新计算布局,这会触发后续的绘制和合成阶段。频繁的重排是导致页面卡顿的常见原因。

// 这段代码触发了多次重排(效率低下)
const element = document.getElementById('myElement');
element.style.width = '100px';  // 第一次重排
element.style.height = '200px'; // 第二次重排
element.style.margin = '10px';  // 第三次重排

// 优化:使用class或requestAnimationFrame批量修改
element.classList.add('new-style');

第四阶段:绘制 - 生成绘制指令

布局确定了每个元素的位置和大小,但还没有实际绘制任何内容。绘制阶段(也称为栅格化)将每个元素分解为多个图层,并生成一系列绘制指令,告诉GPU如何绘制每个像素。

现代浏览器将绘制分为多个步骤:

  1. 绘制列表生成:创建绘制指令列表(“先画背景,然后文本,然后边框...”)

  2. 栅格化:将绘制指令转换为实际像素

  3. 分层与合成:将页面分解为多个图层,分别栅格化后合成

浏览器采用智能分层策略:某些元素(如具有3D变换、透明动画的元素)会自动提升到独立图层,以便单独栅格化和合成。

第五阶段:合成与显示 - 最终呈现

在最后阶段,合成器线程接管工作,将各个图层合成为最终图像。这一步骤在现代浏览器中尤为重要,因为它使GPU加速成为可能。

合成器线程独立于主线程运行,这意味着即使JavaScript执行阻塞了主线程,滚动和动画仍然可以流畅运行(前提是它们只涉及合成属性)。

当页面滚动或发生动画时,合成器可以:

  1. 仅重新合成已变化的图层

  2. 利用GPU并行处理能力

  3. 避免重新运行布局和绘制阶段

/* 这些属性的变化只会触发合成,性能开销小 */
transform: translateX(100px);
opacity: 0.5;

/* 而这些属性变化可能触发重排和重绘,性能开销大 */
width: 500px;
margin-left: 100px;

渲染性能优化启示

理解浏览器渲染逻辑的直接应用是性能优化:

  1. 减少重排:批量DOM读写操作,使用documentFragment进行离线DOM操作

  2. 利用合成器:对动画使用transformopacity属性

  3. 避免布局抖动:不要在循环中连续读取和修改几何属性

  4. 优化CSS选择器:避免过于复杂的选择器,减少样式计算时间

  5. 内容可见性优化:使用content-visibility: auto延迟屏外内容渲染

浏览器的渲染逻辑是一个复杂但高度优化的系统工程。从网络线程接收数据,到主线程解析构建,再到合成器线程和GPU的最终绘制,多个进程和线程协同工作,才能在毫秒级时间内将代码转化为像素。

理解这一过程不仅有助于我们编写更高效的代码,更能让我们欣赏现代浏览器工程背后的精妙设计。每次网页加载,都是一次跨越多个子系统、涉及数百万次计算的微型奇迹——而这一切,就发生在我们按下回车键的那一瞬间。

业务咨询

微信咨询

请扫二维码
咨询项目经理

400电话

4001-355-360

获取方案

与蓝韵项目经理通话

请输入正确的手机号码格式

信息保护中请放心填写

在线咨询
 
提交成功
关闭浮窗