未找到匹配的笔记

从URL输入到页面渲染全过程

浏览器网络

核心流程概览

URL输入 → DNS解析 → TCP连接 → HTTP请求 → 服务器响应 → 浏览器解析 → 渲染页面

整个过程可以分为网络请求阶段浏览器渲染阶段两大核心部分。

阶段一:网络请求阶段

1. URL解析与输入处理

地址栏输入处理

  • 协议识别:浏览器判断输入是URL还是搜索关键词
  • URL规范化:补全协议(如 www.example.comhttps://www.example.com
  • 编码处理:对特殊字符进行URL编码(如空格 → %20

面试要点

  • URL结构协议://域名:端口/路径?查询参数#锚点
  • 同源策略:协议、域名、端口三者相同才同源
  • URL编码encodeURI()encodeURIComponent() 的区别

2. DNS域名解析

解析流程(递归查询 + 迭代查询)

浏览器缓存 → 操作系统缓存 → hosts文件 → 本地DNS服务器 → 根域名服务器 → 顶级域名服务器 → 权威域名服务器

详细步骤

  1. 浏览器DNS缓存

    • 浏览器维护自己的DNS缓存表
    • 缓存时间由TTL(Time To Live)决定
    • 可通过 chrome://net-internals/#dns 查看
  2. 操作系统缓存

    • Windows:ipconfig /displaydns
    • Linux/Mac:/etc/hosts 文件
  3. 本地DNS服务器查询

    • 通常由ISP(互联网服务提供商)提供
    • 如果缓存中没有,开始递归查询
  4. DNS递归/迭代查询

    • 递归查询:客户端 → 本地DNS服务器(客户端只发一次请求)
    • 迭代查询:本地DNS服务器 → 根/顶级/权威服务器(多次往返)
    • 最终获取IP地址并返回

面试要点

  • DNS预解析<link rel="dns-prefetch" href="//example.com">
  • DNS查询类型:A记录(IPv4)、AAAA记录(IPv6)、CNAME(别名)
  • DNS优化:减少DNS查询次数、使用CDN、DNS预解析

3. TCP连接建立(三次握手)

三次握手过程

客户端                         服务器
  |                              |
  |-------- SYN (seq=x) -------->|
  |                              |
  |<-- SYN-ACK (seq=y, ack=x+1) -|
  |                              |
  |------ ACK (ack=y+1) -------->|
  |                              |
  |    连接建立,开始传输数据      |

详细说明

  1. 第一次握手(SYN)

    • 客户端发送SYN包,序列号seq=x,进入SYN_SENT状态
    • 目的:请求建立连接,告知服务器自己的初始序列号
  2. 第二次握手(SYN-ACK)

    • 服务器发送SYN-ACK包,序列号seq=y,确认号ack=x+1,进入SYN_RCVD状态
    • 目的:确认收到客户端请求,同时发送自己的连接请求
  3. 第三次握手(ACK)

    • 客户端发送ACK包,确认号ack=y+1,进入ESTABLISHED状态
    • 服务器收到后也进入ESTABLISHED状态
    • 目的:确认收到服务器的响应,连接正式建立

为什么需要三次握手?

  • 防止历史连接:如果客户端发送的SYN包是旧的(网络延迟),服务器可以通过第三次握手判断并拒绝
  • 同步序列号:双方确认对方的初始序列号,为可靠传输做准备
  • 确认双方通信能力:确保客户端和服务器都能正常收发数据

面试要点

  • 半连接队列:服务器在SYN_RCVD状态维护的队列,可能遭受SYN Flood攻击
  • SYN Cookie:防御SYN Flood攻击的机制
  • TCP vs UDP:TCP可靠但慢,UDP快速但不可靠

4. TLS/SSL握手(HTTPS)

TLS 1.2握手流程(4次往返)

  1. Client Hello

    • 客户端发送:支持的TLS版本、加密套件列表、随机数(Client Random)
  2. Server Hello

    • 服务器选择:TLS版本、加密套件、随机数(Server Random)
    • 发送服务器证书(包含公钥)
  3. 客户端验证与密钥交换

    • 验证证书有效性(CA签名、域名匹配、有效期)
    • 生成预主密钥(Pre-Master Secret),用服务器公钥加密发送
    • 双方根据Client Random + Server Random + Pre-Master Secret 计算主密钥
  4. 完成握手

    • 双方发送Finished消息,使用主密钥加密
    • 验证成功后,开始加密通信

TLS 1.3优化(1次往返)

  • 客户端在第一次就发送密钥交换信息
  • 服务器可以直接响应加密数据,减少往返次数

面试要点

  • 证书链验证:根CA → 中间CA → 服务器证书
  • 对称加密 vs 非对称加密:握手用非对称,传输用对称(性能考虑)
  • 前向安全性:即使私钥泄露,历史会话仍安全

5. HTTP请求发送

请求报文结构

请求行:方法 路径 协议版本
请求头:Host, User-Agent, Accept, Cookie等
空行
请求体:POST/PUT数据

关键请求头

  • Host:目标主机(HTTP/1.1必需,支持虚拟主机)
  • User-Agent:浏览器标识
  • Accept:可接受的响应类型
  • Cookie:携带的Cookie信息
  • Referer:来源页面
  • Cache-Control:缓存控制

HTTP/1.1 vs HTTP/2

HTTP/1.1问题

  • 队头阻塞:同一连接上请求必须串行
  • 连接数限制:浏览器对同一域名限制6-8个连接
  • 头部冗余:每次请求都发送完整头部

HTTP/2优势

  • 多路复用:单一连接上并行传输多个请求/响应
  • 头部压缩:HPACK算法压缩头部
  • 服务器推送:服务器主动推送资源

面试要点

  • HTTP方法:GET(幂等)、POST(非幂等)、PUT、DELETE、PATCH
  • 幂等性:多次执行结果相同
  • 安全性:GET、HEAD是安全的,不会修改服务器状态

6. 服务器处理与响应

服务器处理流程

  1. 接收请求:Web服务器(Nginx、Apache)接收
  2. 路由解析:根据URL路径路由到对应处理程序
  3. 业务处理:执行后端逻辑(数据库查询、业务计算等)
  4. 生成响应:构建HTTP响应报文

响应报文结构

状态行:协议版本 状态码 状态描述
响应头:Content-Type, Content-Length, Set-Cookie等
空行
响应体:HTML、JSON等数据

关键响应头

  • Content-Type:响应体类型(text/html, application/json
  • Content-Length:响应体长度
  • Set-Cookie:设置Cookie
  • Cache-Control:缓存策略
  • Location:重定向地址(3xx状态码)

7. TCP连接关闭(四次挥手)

四次挥手过程

客户端                         服务器
  |                              |
  |-------- FIN (seq=x) -------->|
  |                              |
  |<-- ACK (ack=x+1) ------------|
  |                              |
  |<-- FIN (seq=y) --------------|
  |                              |
  |------ ACK (ack=y+1) -------->|
  |                              |
  |    连接关闭                    |

为什么需要四次挥手?

  • 半关闭状态:一方发送FIN后,仍可接收数据
  • 数据完整性:确保双方数据都发送完毕
  • TIME_WAIT状态:客户端最后ACK后等待2MSL(最大报文段生存时间),防止旧连接数据包干扰新连接

面试要点

  • TIME_WAIT的作用:确保最后一个ACK到达,处理可能的重传
  • CLOSE_WAIT过多:通常是应用层未正确关闭连接
  • SO_REUSEADDR:允许端口复用,解决TIME_WAIT问题

阶段二:浏览器渲染阶段

8. 浏览器解析响应

响应处理流程

  1. Content-Type判断

    • text/html → HTML解析器处理
    • application/json → JSON解析
    • image/png → 图片解码
    • application/javascript → JavaScript引擎执行
  2. 字符编码解析

    • 根据HTTP响应头 Content-Type: text/html; charset=utf-8
    • 或HTML中的 <meta charset="utf-8">
    • 将字节流转换为字符流

9. HTML解析与DOM构建

解析流程

字节流 → 字符流 → Token(令牌)→ 节点(Node)→ DOM树

详细步骤

  1. 词法分析(Tokenization)

    • HTML解析器将字符流转换为Token
    • Token类型:开始标签、结束标签、文本、注释等
  2. 语法分析(DOM树构建)

    • 根据Token构建DOM节点
    • 遇到开始标签创建元素节点
    • 遇到文本创建文本节点
    • 遇到结束标签闭合当前节点
  3. DOM树构建算法

    • 使用栈结构维护节点层级关系
    • 遇到开始标签入栈,遇到结束标签出栈

解析过程中的资源加载

  • 遇到 <script>:阻塞解析,下载并执行脚本
  • 遇到 <link>:异步下载CSS,不阻塞解析
  • 遇到 <img>:异步下载图片,不阻塞解析

面试要点

  • 解析阻塞<script> 会阻塞DOM构建,asyncdefer 的区别
  • DOMContentLoaded vs load:DOMContentLoaded是DOM构建完成,load是所有资源加载完成
  • 回流与重绘:DOM操作可能触发回流(reflow)和重绘(repaint)

10. CSS解析与CSSOM构建

CSS解析流程

CSS字节流 → 字符流 → Token → CSS规则 → CSSOM树

CSSOM树结构

  • 规则匹配:根据选择器匹配元素
  • 样式计算:计算每个元素的最终样式(继承、层叠、优先级)
  • CSSOM树:表示样式规则之间的层级关系

样式计算关键点

  1. 继承:某些属性会从父元素继承(如 color, font-size
  2. 层叠:多个规则作用于同一元素时的优先级
  3. 优先级!important > 内联样式 > ID选择器 > 类选择器 > 标签选择器

面试要点

  • CSS阻塞渲染:CSS会阻塞渲染树的构建,但不阻塞DOM构建
  • 选择器性能:从右到左匹配,避免深层嵌套和通配符
  • 重排(Reflow):改变元素几何属性(宽高、位置)触发
  • 重绘(Repaint):改变元素外观属性(颜色、背景)触发

11. 渲染树(Render Tree)构建

构建过程

  1. 遍历DOM树:从根节点开始
  2. 可见性检查:过滤不可见节点(display: none 不加入渲染树,visibility: hidden 会加入)
  3. 样式匹配:为每个可见节点匹配CSS规则
  4. 计算样式:计算最终的计算样式(computed style)

渲染树特点

  • 只包含可见元素
  • 每个节点包含完整的样式信息
  • 是DOM和CSSOM的结合

12. 布局(Layout/Reflow)

布局流程

  1. 计算几何信息:根据CSS盒模型计算每个元素的位置和大小
  2. 盒模型计算
    • width/height:内容区域
    • padding:内边距
    • border:边框
    • margin:外边距
  3. 定位计算
    • 正常流(Normal Flow)
    • 浮动(Float)
    • 绝对定位(Absolute)
    • 固定定位(Fixed)

布局算法

  • 块级格式化上下文(BFC):独立的布局环境
  • 弹性布局(Flexbox):一维布局
  • 网格布局(Grid):二维布局

面试要点

  • 触发回流的操作:修改DOM结构、改变元素尺寸、改变窗口大小
  • 优化策略:批量DOM操作、使用 transform 代替 top/left、使用 DocumentFragment
  • BFC应用:清除浮动、防止margin重叠、自适应布局

13. 分层(Layer)与合成(Composite)

分层原因

  • 提升性能:某些元素独立一层,变化时只需重绘该层
  • 硬件加速:利用GPU加速渲染

分层触发条件

  • transformopacitywill-change 等属性
  • 视频、Canvas、iframe等元素
  • 有层叠上下文(z-index)的元素

合成流程

  1. 绘制列表:为每层生成绘制指令
  2. 栅格化(Rasterization):将绘制指令转换为位图
  3. 合成(Compositing):将各层位图合成为最终画面

面试要点

  • GPU加速:使用 transformopacity 触发硬件加速
  • 重排 vs 重绘 vs 合成:重排最耗性能,合成性能最好
  • will-change:提前告知浏览器元素将变化,优化分层

14. 绘制(Paint)与显示

绘制流程

  1. 主线程绘制:生成绘制指令列表
  2. 合成线程处理:将绘制指令提交给合成线程
  3. GPU栅格化:将绘制指令转换为像素
  4. 显示:将最终画面显示到屏幕

渲染优化

  • 避免强制同步布局:避免在读取布局信息前修改DOM
  • 使用 requestAnimationFrame:在下一帧渲染前执行动画
  • 虚拟滚动:只渲染可见区域
  • 代码分割:按需加载资源

性能优化关键点

网络阶段优化

  1. DNS优化:DNS预解析、使用CDN
  2. TCP优化:HTTP/2、HTTP/3(QUIC)
  3. 资源优化:压缩、缓存、CDN、资源优先级

渲染阶段优化

  1. 关键渲染路径优化:内联关键CSS、延迟非关键CSS
  2. JavaScript优化async/defer、代码分割、Tree Shaking
  3. 避免强制同步布局:批量读取布局信息
  4. 使用合成层transformopacity 触发GPU加速

面试高频问题

  1. DNS解析过程?如何优化?
  2. 三次握手和四次挥手的详细过程?为什么需要?
  3. HTTPS握手过程?TLS 1.3的优化?
  4. HTTP/1.1和HTTP/2的区别?
  5. 浏览器渲染流程?重排和重绘的区别?
  6. 如何优化首屏渲染时间?
  7. <script> 标签的 asyncdefer 区别?
  8. DOMContentLoaded 和 load 事件的区别?