从输入 URL 到页面渲染经历了什么?

2 天前
/
3
摘要
用户输入URL → URL解析 → DNS解析(查缓存 →递归/迭代查询获取IP) → 建立TCP连接(三次握手) → (HTTPS) TLS握手 → 发送HTTP请求 → 服务器处理请求返回HTTP响应 → 浏览器接收响应 → 解析HTML构建DOM树 → 解析CSS构建CSSOM树 → 合并DOM+CSSOM形成渲染树(Render Tree) → 布局计算/回流(计算位置尺寸) → 绘制/光栅化(生成像素位图) → 合成与显示(合层并输出到屏幕)

从输入 URL 到页面渲染经历了什么?

​URL 解析与输入处理​

  • 行为: 用户在地址栏输入 URL 并按下回车。
  • 解析: 浏览器解析 URL,检查协议(http/https)、域名、端口、路径、查询参数等。
  • 处理: 浏览器可能执行自动补全、历史记录匹配或调用搜索引擎(如果是关键字而非合法 URL)。

​DNS 域名解析​

  • 目的: 将人类可读的域名(如 www.example.com)转换为机器可识别的 IP 地址
  • 过程:
    1. 检查 浏览器缓存 中是否有该域名的 DNS 记录。
    2. 检查 操作系统缓存 (如 Hosts 文件、系统 DNS 缓存)。
    3. 检查 本地路由器缓存
    4. ISP 的 DNS 服务器 发起递归查询。
    5. 如果 ISP DNS 没有,则进行迭代查询:从根域名服务器 -> 顶级域名服务器 (.com) -> 权威域名服务器 (负责 example.com) 逐级查询,最终获取目标 IP。

​建立 TCP 连接(三次握手)​​

  • 目的: 与目标服务器建立可靠的传输通道。
  • 过程:
    1. 客户端发送 SYN:向服务器端口(通常是 80 或 443)发送一个 SYN 包,并带上初始序列号。
    2. 服务器响应 SYN-ACK:收到 SYN 后,服务器发送一个 SYN-ACK 包(包含自己的序列号和确认号)。
    3. 客户端发送 ACK:客户端收到 SYN-ACK 后,再发送一个 ACK 包进行确认。此时连接建立成功。

TLS/SSL 握手(仅 HTTPS)​​

  • 目的: 建立安全加密的连接通道。
  • 过程(简化):
    1. Client Hello:客户端发送支持的加密套件列表、随机数等信息。
    2. Server Hello:服务器选择加密套件,发送证书、随机数等。
    3. 验证证书:客户端验证服务器证书的有效性(颁发机构、域名、有效期)。
    4. 生成会话密钥:客户端生成预主密钥并用服务器公钥加密发送给服务器。双方通过预主密钥和之前的随机数计算出会话密钥
    5. 完成握手:双方交换加密信息验证加密通道建立成功。

发送 HTTP 请求​

  • 浏览器基于 URL 路径和方法(GET/POST 等),结合之前解析出的信息,构建一个完整的 HTTP 请求报文
  • 内容:
    • 请求行:方法 URL 协议版本 (e.g., GET /index.html HTTP/1.1)
    • 请求头:包含 Host、User-Agent、Cookie、Accept、Connection 等重要信息。
    • 请求体(如果是 POST/PUT 等方法)。
  • 这个请求报文通过已建立的 TCP/TLS 连接发送给服务器。

服务器处理请求并返回响应

  • 服务器接收请求报文,根据 URL、方法、请求头等信息进行处理:
    • 后端应用逻辑处理(如路由分发、数据库查询)。
    • 生成 HTTP 响应。
  • 构建 HTTP 响应报文:
    • 状态行:协议版本 状态码 状态短语 (e.g., HTTP/1.1 200 OK404 Not Found)。
    • 响应头:包含 Content-Type、Content-Length、Set-Cookie、Cache-Control、Server 等信息。
    • 响应体:包含请求的资源(如 HTML 文件内容)。

浏览器接收响应与处理​

  • 浏览器接收服务器发送的 HTTP 响应数据流。
  • 解析状态码:判断请求成功 (2xx)、重定向 (3xx)、客户端错误 (4xx)、服务端错误 (5xx)。
  • 根据响应头Content-Type (e.g., text/html) 判断如何处理响应体。

解析 HTML 构建 DOM 树

  • 过程:
    1. 转换(Conversion):浏览器将接收到的原始字节根据编码规则(如 UTF-8)转换成字符。
    2. 标记化(Tokenization):分词器(Tokenizer)将字符流拆解成符合 HTML 标准的标记(Tokens)。
    3. 构建节点(Node Construction):语法解析器(Parser)根据标记及其层级关系,创建节点对象。
    4. 构建 DOM 树(DOM Tree):节点被组织成一个树状结构(Document Object Model),反映了 HTML 的嵌套关系。

解析 CSS 构建 CSSOM 树​

  • 过程:
    1. 字节->字符->Tokens: 类似 HTML 解析,将 CSS 字节流转换为 Tokens。
    2. 构建规则树: 解析器处理 Tokens 和属性关系,构建 CSSOM (CSS Object Model) 树。CSSOM 同样具有层级结构,包含继承和层叠规则

合并 DOM 和 CSSOM 形成渲染树(Render Tree)​​

  • 目的: 构建一个仅包含可见内容及其最终计算样式的树结构,用于实际绘制。
  • 过程:
    • 从 DOM 树的根节点开始遍历。
    • 对于每个可见节点(非 display: none;、非 head、非 script 标签),找到其在 CSSOM 中对应的样式规则。
    • 将两者结合,创建渲染树节点(Render Object)。
    • 不可见节点(如 meta, script, head,或被隐藏的元素)不会添加到渲染树中。

布局/回流(Layout/Reflow)​​

  • 目的: 计算渲染树中每个节点在视口(viewport) 中的确切位置(坐标)和尺寸(宽高)
  • 过程:
    • 从根节点开始递归遍历渲染树。
    • 计算每个节点的几何信息(位置、尺寸)。这个过程依赖于 CSS 盒模型(内容、内边距、边框、外边距)以及 width, height, position, float 等样式属性。
    • 输出一个包含所有节点几何信息的“盒子模型”。
    • 触发点: 首次页面加载必然触发。后续 DOM 结构变化、样式改变、窗口大小调整(resize)都可能触发局部或全局回流(代价高昂,应尽量避免)。

绘制/光栅化(Painting/Rasterization)​​

  • 目的: 将布局阶段计算出的每个节点,转换为屏幕上实际的像素点
  • 过程:
    1. 创建绘制记录(Paint Records): 将绘制操作(如绘制文本、颜色填充、边框、图像)分解并记录到一个列表中。
    2. 光栅化: 浏览器将绘制指令发送给 GPU 图形进程,将渲染树分割成不同的图层进行光栅化处理(由渲染引擎根据规则自动分层,如 position: fixed、3D 变换、<video>、Canvas 通常单独分层)。这步不是指最终显示在屏幕上。
    3. 分块(Tiling): 将每个图层划分成更小的图块(Tiles)
    4. 栅格化线程(Raster Thread): 后台线程将图块转换为位图(Bitmap)(存储在内存中)。

合成与显示(Compositing & Display)​​

  • 目的: 将处理好的像素信息最终显示到用户屏幕。
  • 过程:
    1. 合成(Compositing):
      • 合成器线程收集绘制层(即栅格化后的图块位图信息) 以及合成信息(位置、深度、变换等)。
      • 将这些层按照正确的顺序(层级 z-index)和位置合成一个最终画面
    2. 显示(Display):
      • 合成后的完整画面被提交给图形硬件(通常是计算机的 GPU)。
      • GPU 将画面输出到显示器的帧缓冲区(Frame Buffer)
      • 显示器按照固定刷新率(如 60Hz)从帧缓冲区读取数据并显示在屏幕上。
  • 优势: 只需对变化的图层(或图层的一部分)进行重绘和重新合成,性能比全局重绘高得多。通过提升特定元素的 will-changetransform 属性可以创建新的合成层。

⚡ 关键性能优化点(作为前端工程师的施展空间)

  1. DNS 预取 & 预连接: <link rel="dns-prefetch" href="//example.com"><link rel="preconnect" href="https://example.com">
  2. 减少关键请求链/资源体积:
    • 代码分割(Code Splitting)、懒加载(Lazy Loading)、Tree Shaking。
    • 压缩资源(JS/CSS/Minify Images)。
    • 利用 HTTP/2 或 QUIC 的多路复用减少连接开销。
  3. 缓存策略:
    • 强缓存(Expires/Cache-Control) 避免重复请求。
    • 协商缓存(ETag/Last-Modified) 验证资源是否更新。
  4. 优化渲染性能:
    • 避免阻塞渲染的 JS/CSS:JS 放底部或 defer/async, CSS 内联关键路径或异步加载非关键 CSS。
    • 减少/优化回流(Reflow):避免频繁操作 DOM/样式,善用 transform/opacity 等只触发合成(Composite)的属性,批量 DOM 更新(如 DocumentFragment)。
    • 优化绘制(Paint):减少复杂的绘制区域和重复绘制。
    • GPU 加速/分层合成: 适度使用 will-changetransform: translateZ(0) 创建独立合成层(需权衡内存消耗)。
  5. CDN 加速静态资源分发

总结


用户输入URL
  → URL解析
  → DNS解析(查缓存 →递归/迭代查询获取IP)
  → 建立TCP连接(三次握手)
  → (HTTPS) TLS握手
  → 发送HTTP请求
  → 服务器处理请求返回HTTP响应
  → 浏览器接收响应
  → 解析HTML构建DOM树
  → 解析CSS构建CSSOM树
  → 合并DOM+CSSOM形成渲染树(Render Tree)
  → 布局计算/回流(计算位置尺寸)
  → 绘制/光栅化(生成像素位图)
  → 合成与显示(合层并输出到屏幕)

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...