前端基础:从浏览器渲染原理到性能优化

浏览器渲染流程

当我们输入 URL 到页面呈现在屏幕上,浏览器主要经历以下几个阶段:

1. 解析阶段

浏览器接收到 HTML 字节流后,会经过以下转换:

字节 → 字符 → Token → 节点 → DOM 树

同时,CSS 也会被解析为 CSSOM(CSS Object Model):

// CSSOM 的结构示例
const cssom = {
  rules: [
    {
      selector: 'body',
      styles: { fontSize: '16px', color: '#333' }
    }
  ]
};

2. 样式计算

将 DOM 和 CSSOM 合并,生成渲染树(Render Tree):

  • 只包含可见元素(display: none 的元素不包含)
  • 每个节点都有计算后的样式

3. 布局(Layout)

计算每个节点的几何信息:

/* 盒模型决定了元素的布局 */
.box {
  width: 200px;
  height: 100px;
  padding: 16px;
  margin: 8px;
  /* 实际占用宽度 = 200 + 16*2 + 8*2 = 248px (content-box) */
}

4. 绘制(Paint)

将布局信息转换为屏幕上的像素点。

性能优化策略

关键渲染路径优化

<!-- 内联关键 CSS -->
<style>
  .above-the-fold { /* 首屏样式 */ }
</style>

<!-- 异步加载非关键 CSS -->
<link rel="preload" href="non-critical.css" as="style"
      onload="this.onload=null;this.rel='stylesheet'">

减少重排(Reflow)

// 不好的写法 - 触发多次重排
element.style.width = '100px';
element.style.height = '100px';
element.style.margin = '10px';

// 好的写法 - 一次重排
element.style.cssText = 'width: 100px; height: 100px; margin: 10px;';
// 或者使用 class
element.classList.add('new-style');

虚拟列表

当列表数据量很大时,使用虚拟列表只渲染可视区域的元素:

// 虚拟列表核心思路
const visibleCount = Math.ceil(viewportHeight / itemHeight);
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = startIndex + visibleCount;

// 只渲染 startIndex 到 endIndex 的元素
renderItems(list.slice(startIndex, endIndex));

总结

理解浏览器渲染原理是前端性能优化的基础。记住关键路径:DOM → CSSOM → Render Tree → Layout → Paint,针对性地优化每个环节。