最详细的从输入 URL 到页面渲染完整流程说明,看完还不懂捶我

62 阅读13分钟

从输入 URL 到页面渲染完整流程详解


目录


一、从输入 URL 到发起网络请求前

1.1 地址栏输入与协议/目标识别

当你在浏览器中输入:

https://www.baidu.com/

浏览器会进行以下判断:

  • 判断输入类型
    • 如果输入符合 URL 格式(如 https://www.baidu.com/)→ 当作 URL 处理
    • 如果输入是普通文本 → 可能走默认搜索引擎
  • 解析 URL 结构
    • 协议https
    • 主机名www.baidu.com
    • 端口:默认 443(HTTPS)
    • 路径/(根路径)

1.2 浏览器进程与渲染进程协调

现代浏览器一般采用多进程架构(以 Chrome 为例):

  • 浏览器进程:负责 UI、网络、进程管理等
  • 渲染进程:负责每个 Tab 的页面渲染、JS 执行

流程:

  • 浏览器进程接收到导航请求(你敲回车)
  • https://www.baidu.com/ 选择或创建一个新的 渲染进程
  • 在真正开始加载前,会先进行 安全策略检查(比如 HSTS、本地策略等)

二、DNS 解析:把域名解析为 IP

2.1 查找本地缓存与系统缓存

目标是把 www.baidu.com 解析为 IP 地址(例如 220.x.x.x,具体由 DNS 解析结果决定):

浏览器会依次查询:

  1. 浏览器自身 DNS 缓存
    • 如果近期访问过,可能已有缓存条目
  2. 本机操作系统 DNS 缓存
  3. hosts 文件
    • 如 Windows 的 C:\Windows\System32\drivers\etc\hosts,如果有显式映射,则直接使用

2.2 递归 DNS 查询(若本地未命中)

如果上述均未命中,操作系统会向配置的 本地域名服务器(通常为路由器或 ISP DNS)发起请求,具体流程:

  • 本地 DNS 服务器如果没有缓存,则进行递归查询:
    1. 访问 根域名服务器(.) → 找到 .com 顶级域名服务器
    2. .com TLD 服务器 查询 baidu.com → 获得权威 DNS 服务器地址
    3. baidu.com 的权威 DNS 查询 www.baidu.com → 得到最终 IP
  • 结果在各级 DNS 缓存中存储一段时间(TTL)

浏览器最终拿到 www.baidu.com 对应的 一个或多个 IP 地址


三、建立连接(TCP 三次握手 + TLS 握手)

3.1 选择 IP 与端口

浏览器:

  • 可能有多个 IP(多机房/多 CDN 节点),根据策略选择一个
  • 对于 https,默认端口为 443

3.2 TCP 三次握手

在客户端和服务器之间建立 TCP 连接(可靠的字节流通道):

  1. SYN:客户端 → 服务器,发送 SYN 包请求建立连接
  2. SYN-ACK:服务器 → 客户端,确认并同意连接
  3. ACK:客户端 → 服务器,确认收到,连接建立

此时,TCP 连接已建立,但 HTTPS 还未开始加密通信。

3.3 TLS/SSL 握手(HTTPS)

为实现加密通信和身份验证,进行 TLS 握手:

  1. ClientHello
    • 浏览器发送支持的 TLS 版本、加密套件列表、随机数等
  2. ServerHello + 证书
    • 服务器选择加密套件,返回:
      • 服务器证书(包含 baidu.com*.baidu.com 的公钥信息)
      • 服务器随机数等
  3. 证书验证(前端本机执行)
    • 浏览器在本地:
      • 检查证书是否由受信任 CA 签发
      • 检查证书域名是否与 www.baidu.com 匹配
      • 检查证书有效期、是否被吊销等
    • 如果验证失败,会弹出安全告警
  4. 生成对称密钥
    • 根据协商的算法(如 ECDHE),客户端与服务器共同生成 会话密钥
    • 使用服务器公钥和密钥交换算法生成、协商对称密钥
  5. 完成握手
    • 双方使用对称密钥进行后续所有数据加解密

此时,安全加密信道建立完成


四、HTTP 请求与首个响应(HTML 文档)

4.1 发送首个 HTTP 请求

浏览器通过已建立的 TLS+TCP 连接发送 HTTP 请求:

  • 请求行
GET / HTTP/1.1
  • 请求头(示例)
    • Host: www.baidu.com
    • User-Agent: ...(浏览器信息)
    • Accept: text/html,application/xhtml+xml,application/xml,...
    • Accept-Language: zh-CN,zh;q=0.9,...
    • Cookie: ...(此前在 baidu.com 下存储的 cookie)
    • Connection: keep-alive
    • Upgrade-Insecure-Requests: 1
    • 等等…

4.2 服务器处理请求(后端)

虽然这是后端行为,但前端需要理解结果:

  • 服务器根据请求路径 /、cookie、UA 等:
    • 做路由与鉴权
    • 查询数据库、调用内部服务
    • 生成 HTML 或响应一个重定向(例如 302 到某个特定路径)
  • 如果是重定向,浏览器会 再次发起请求 到新的 URL(重复上述一部分流程,但通常复用同一连接)

4.3 接收首个 HTTP 响应

服务器返回:

  • 状态行:如 HTTP/1.1 200 OK
  • 响应头(关键跟前端相关):
    • Content-Type: text/html; charset=UTF-8
    • Content-Length: ...
    • Cache-Control, ETag, Last-Modified 等缓存策略
    • Set-Cookie(设置或更新 cookie)
    • Content-Encoding: gzip/br(压缩)
    • Strict-Transport-Security(强制 HTTPS)
    • Server, Date
  • 响应体:HTML 文档内容(比如百度首页的 HTML 结构)

浏览器解压编码(如 gzip/br),得到原始 HTML 文本。


五、浏览器渲染流水线(HTML → 最初可见页面)

从这里开始,前端工程师最关心的 渲染流程

5.1 构建 DOM(解析 HTML)

  • 边下载边解析
    • HTML 数据流从网络层到达渲染进程后,HTML 解析器会 一边接收、一边解析
  • 解析过程
    1. 词法分析(Tokenizer):将字节流解码为字符、再分成标签、文本、注释等 token
    2. 语法分析(Parser):根据 HTML 规范生成树形结构——DOM(Document Object Model)
  • 特殊标签处理
    • <script> 遇到非 defer/async 的脚本通常会 阻塞解析,必须先下载并执行,再继续往后解析
    • <link rel="stylesheet">(CSS)通常会 阻塞后续渲染阶段(影响样式计算)

5.2 加载外部资源(CSS/JS/图片等)

当解析到外链资源时:

  • <link rel="stylesheet" href="..."> → 加入 CSS 下载队列
  • <script src="..."> → 加入 JS 下载队列(同步/异步的行为不同)
  • <img src="..."><video><audio><iframe> 等 → 各自加入下载队列
  • 浏览器有资源 并发下载限制(通常每个域名有限制),会进行优先级调度:
    • HTML/CSS/同步 JS 优先级更高
    • 图片、视频等次之

5.3 构建 CSSOM(解析 CSS)

当 CSS 文件(或 <style> 内嵌 CSS)下载完成后:

  1. 解析 CSS 文本 → 构建 CSSOM(CSS Object Model)
  2. 处理:
    • 选择器解析(如 .logo, #header, div > p 等)
    • 继承与层叠(Cascade),计算出每个选择器的 优先级(specificity)
  3. 最终用于后续样式计算

5.4 构建 Render Tree(渲染树)

有了 DOMCSSOM 后:

  1. 将二者结合,计算每个 DOM 节点的 最终计算样式(Computed Style)
  2. 过滤掉 不可见的节点(如 display: none 的元素),生成 Render Tree
    • Render Tree 的节点与 DOM 不完全一一对应
    • 某些 DOM 节点不会生成渲染对象

5.5 布局(Layout / Reflow)

在 Render Tree 上进行布局计算:

  • 确定每个渲染对象的:
    • 几何信息(位置 x,y,尺寸 width/height
    • box modelpositionflex/grid 等影响
  • 会从根节点(如 html)开始,自上而下计算:
    • 父元素决定子元素的可用空间和布局方式

布局完成后,浏览器已经知道 每个可见元素的精确位置与大小

5.6 绘制(Painting)与合成(Compositing)

  1. 绘制列表(Paint)
    • 浏览器遍历 Render Tree,生成绘制指令列表(如背景、文本、边框、阴影等)
  2. 分层(Layering)
    • 具有特定属性的元素会被提升为 独立图层(如 3D transform、position: fixed、某些动画元素)
  3. 栅格化(Rasterization)
    • 图层在 GPU 进程中被栅格化成位图纹理(Tiles)
  4. 合成(Compositing)
    • 在 GPU 上将各图层根据层级、透明度等规则合成最终画面
  5. 首屏渲染
    • 首次绘制完成后,用户能看到 "首屏内容"

此时,页面可能还在继续加载资源,但已经 可见可操作


六、JS 执行、异步网络请求与后续渲染更新

6.1 执行同步 JS

在 HTML 解析阶段:

  • 遇到 <script> 标签(同步加载,未带 async / defer):
    • 如果 src 外链,则先阻塞解析,下载脚本
    • 下载完成后在 主线程执行 JS
  • JS 执行期间可以:
    • 读写 DOM(document.getElementById, innerHTML 等)
    • 读写样式(element.stylegetComputedStyle
    • 注册事件监听(addEventListener
    • 发送 Ajax / Fetch 请求

执行完毕后,HTML 解析器继续往下解析。

6.2 async / defer 脚本与模块脚本

  • <script async>
    • JS 文件下载 与 HTML 解析并行
    • 一旦下载完成,立即执行(可能在 DOMReady 前后不确定)
  • <script defer>
    • JS 文件下载与解析并行
    • 在 DOM 解析完成后按顺序执行(在 DOMContentLoaded 前)
  • type="module"
    • 默认 defer 行为,支持 ES Modules 的导入导出

这些策略影响 首屏渲染速度JS 执行时机

6.3 异步网络请求(XHR / Fetch / WebSocket)

JS 执行中常发起二次请求:

  • XMLHttpRequest / Fetch
    • 通常用于获取 JSON 数据、模板等
    • 请求完成后通过回调 / Promise / async-await 更新 DOM
  • WebSocket
    • 建立长连接,实现实时通信
  • EventSource / SSE
    • 服务器推送

每次异步数据返回后,如果 JS 修改 DOM 或样式,都会引发 回流(Reflow)或重绘(Repaint)

6.4 回流(Reflow)与重绘(Repaint)

  • 回流(Layout/Reflow):当更改影响到 布局(如元素尺寸、结构、字体大小等):
    • 需要重新计算部分或全部的布局
    • 随后进行绘制和合成
  • 重绘(Repaint):仅更改 外观 不影响布局(如 colorbackground):
    • 只需重新绘制,不必重新布局
  • 浏览器会尽量合并这些操作,以减少性能损耗

6.5 事件循环(Event Loop)与页面交互

页面进入稳定阶段后:

  • 浏览器主线程执行 事件循环
    • 从任务队列中取出任务(如用户交互事件、定时器回调、网络回调)
    • 执行回调 → 更新 DOM → 再次触发渲染流程(布局/绘制等)
  • 用户与页面交互(输入搜索词、点击按钮)时:
    • 事件被分发到页面 JS 事件监听器
    • 业务逻辑处理、再次发起网络请求、更新 DOM,渲染刷新

七、缓存、优化与后续访问

7.1 HTTP 缓存

浏览器会根据响应头进行缓存管理:

  • 强缓存Cache-Control: max-age=...Expires
    • 在有效期内,直接使用本地缓存,不会访问服务器
  • 协商缓存
    • 使用 ETag / If-None-MatchLast-Modified / If-Modified-Since
    • 如果资源未变更,服务器返回 304 Not Modified,节省带宽

这会极大提升下次打开页面的速度。

7.2 连接复用与 HTTP/2 / HTTP/3

现代站点通常使用:

  • HTTP/2HTTP/3
    • 多路复用:一个连接上传输多个请求/响应,减少 TCP 连接开销
    • 头部压缩、服务器推送(H2)等
  • 这些都在网络层提升整体加载性能

7.3 Service Worker 与离线缓存(若站点支持 PWA)

如果网站注册了 Service Worker

  • 首次访问时安装 SW,后续请求会被 SW 拦截
  • 可实现:
    • 请求缓存策略控制(Cache First、Network First 等)
    • 离线访问部分资源
    • 后台同步、推送等能力

八、完整流程图

image.png

九、面试高频考点总结

9.1 从地址栏到发请求前发生了什么?

答案要点

  • 解析输入:判断是 URL 还是搜索关键字;解析出协议/域名/端口/路径
  • 进程准备:浏览器进程选择/创建渲染进程,做基础安全检查
  • DNS 解析:依次查浏览器缓存 → 系统缓存 → hosts → 本地 DNS → 根/TLD/权威 DNS,得到 IP
  • 建立连接:TCP 三次握手 + TLS 握手(HTTPS),验证证书、协商对称密钥

9.2 HTTP 请求和响应关键点?

答案要点

  • 请求GET / HTTP/1.1 + 各类请求头(Host、UA、Cookie、Accept 等)
  • 响应:状态码(200/301/302/304 等)、Content-Type、缓存相关头(Cache-Control/ETag/Last-Modified)、Set-Cookie
  • 重定向/缓存:可能 301/302 重定向,304 协商缓存,下次访问可能直接走强缓存

9.3 浏览器渲染主流程?(核心背诵点)

答案要点

  • HTML 解析:字节流 → 字符 → Token → DOM 树,遇到同步 <script> 会阻塞解析
  • CSS 解析:加载 <link>/<style>,解析为 CSSOM
  • 构建渲染树:DOM + CSSOM → Render Tree(过滤 display:none 等不可见节点)
  • 布局(Reflow/Layout):计算每个渲染对象的几何信息(位置、尺寸)
  • 绘制(Paint):生成绘制指令,分层、栅格化
  • 合成(Compositing):GPU 合成各图层,输出到屏幕 → 首屏渲染完成

9.4 JS 在里面扮演什么角色?

答案要点

  • 同步脚本:阻塞 HTML 解析;常用于首屏逻辑、早期初始化
  • async/defer/module:决定下载与执行时机,影响首屏性能
  • 执行后续逻辑:发起 XHR/Fetch/WebSocket,操作 DOM/CSS,驱动交互和数据更新

9.5 回流(Reflow)与重绘(Repaint)区别?

答案要点

  • 回流:布局信息变化(尺寸/位置/结构/字体大小等)→ 重新计算布局 → 之后一般还要重绘和合成,开销更大
  • 重绘:仅视觉样式改变(颜色、背景等)但不影响布局 → 只需重新绘制
  • 优化方向:减少不必要回流、批量 DOM 操作、使用 transform/opacity 动画、合理拆分图层等

9.6 后续访问为什么快?(性能与缓存)

答案要点

  • HTTP 缓存:强缓存(max-age)直接用本地;协商缓存(ETag/Last-Modified)返回 304
  • 连接复用:HTTP/2/HTTP/3 多路复用、头部压缩
  • Service Worker(若有):拦截请求,走自定义缓存策略甚至离线访问

9.7 极简 10 句版(快速口述)

  1. 输入 URL,浏览器解析协议、域名、端口、路径
  2. DNS 解析:查缓存 → 本地 DNS → 根/TLD/权威 DNS,得到 IP
  3. TCP 三次握手建立连接
  4. HTTPS 进行 TLS 握手:验证证书、协商密钥
  5. 发送 HTTP 请求(GET /),服务器返回 HTML
  6. HTML 解析构建 DOM 树(遇到同步 script 会阻塞)
  7. 加载 CSS 构建 CSSOM,DOM + CSSOM → Render Tree
  8. 布局(Layout)计算元素位置尺寸,绘制(Paint)生成绘制列表
  9. 分层、栅格化、合成(Compositing),首屏渲染完成
  10. JS 执行、异步请求、事件循环持续响应交互,触发回流/重绘更新页面

十、性能优化建议

10.1 DNS 优化

  • 使用 DNS 预解析<link rel="dns-prefetch" href="//www.example.com">
  • 减少域名数量(减少 DNS 查询次数)
  • 使用 CDN 加速 DNS 解析

10.2 网络连接优化

  • 使用 HTTP/2HTTP/3(多路复用、头部压缩)
  • TCP 预连接<link rel="preconnect" href="https://www.example.com">
  • 使用 CDN 就近访问,减少延迟

10.3 资源加载优化

  • 关键资源优先:内联关键 CSS,延迟非关键 CSS
  • JS 优化
    • 使用 deferasync 避免阻塞解析
    • 代码分割、按需加载
    • Tree Shaking 减少体积
  • 图片优化
    • 使用 WebP、AVIF 等现代格式
    • 懒加载(loading="lazy"
    • 响应式图片(srcset

10.4 渲染优化

  • 减少回流/重绘
    • 批量 DOM 操作(使用 DocumentFragment)
    • 使用 transformopacity 做动画(触发合成层)
    • 避免频繁读取布局属性(如 offsetWidth
  • CSS 优化
    • 避免深层嵌套选择器
    • 减少 @import(阻塞渲染)
    • 使用 will-change 提示浏览器优化

10.5 缓存策略

  • HTTP 缓存:合理设置 Cache-ControlETag
  • Service Worker:实现离线缓存、后台更新
  • 浏览器缓存:利用 LocalStorage、SessionStorage、IndexedDB

10.6 代码层面优化

  • 首屏优化
    • SSR(服务端渲染)或 SSG(静态生成)
    • 骨架屏、占位符
  • 懒加载:路由懒加载、组件懒加载
  • 防抖/节流:优化事件处理频率