将在浏览器地址栏输入url到页面加载出来的整个过程配合着浏览器进程和线程进行一个全面的梳理。
前置知识:浏览器的多进程/线程架构
现代浏览器(Chrome/Edge/Firefox)采用"多进程架构",核心目的是隔离风险(一个页面崩溃不影响整个浏览器)、提升性能。在讲解流程前,先明确核心进程/线程的职责:
| 进程类型 | 核心职责 | 关键线程 |
|---|---|---|
| 浏览器主进程(Browser进程) | 地址栏输入、前进后退、窗口管理、进程调度、缓存管理、用户交互 | 无(仅负责调度其他进程) |
| 网络进程 | 处理所有网络请求(DNS解析、TCP连接、HTTP请求/响应、缓存读取) | DNS线程、TCP线程、请求线程(多个,并行处理) |
| 渲染进程(Renderer进程) | HTML/CSS解析、JS执行、DOM/CSSOM构建、布局、绘制、合成 | GUI渲染线程、Js引擎线程、事件触发线程、定时触发器线程、异步http请求线程 |
| GPU进程 | 图层合成、硬件加速渲染、屏幕显示 | GPU线程 |
| 插件进程 | 处理插件(如Flash,已逐步淘汰) | 插件线程 |
关键提醒:渲染进程是核心,每个标签页对应一个渲染进程,所有页面渲染相关的操作都在这个进程内完成。
完整流程拆解:从输入URL到页面加载(11步,含进程/线程分工)
总流程图
第一步:输入URL并回车(浏览器主进程)
-
浏览器主进程接收你的输入(如
https://www.baidu.com),并判断输入类型:- 若为搜索关键词(如"前端面试"),自动拼接默认搜索引擎URL(如
https://www.baidu.com/s?wd=前端面试); - 若为合法URL(如
https://www.baidu.com),直接进入导航流程。
- 若为搜索关键词(如"前端面试"),自动拼接默认搜索引擎URL(如
-
主进程清空当前标签页的旧页面(若有),显示"加载中"状态,同时触发后续的缓存查询和网络请求流程。
第二步:查找缓存(浏览器主进程 + 网络进程)
浏览器的核心优化手段之一就是"缓存",目的是减少网络请求,提升加载速度:
- 浏览器主进程先查询「本地缓存」,按优先级顺序校验:内存缓存 → 磁盘缓存 → 协商缓存 → 强缓存;
- 若缓存命中(且未过期):主进程直接将缓存资源传递给渲染进程,跳过后续所有网络请求步骤,页面快速显示;
- 若缓存未命中:主进程通过IPC(进程间通信)通知「网络进程」,启动网络请求流程。
第三步:DNS解析(网络进程)
我们输入的是域名(如 www.baidu.com),但计算机之间通信需要IP地址(如 14.215.177.38),DNS解析就是"将域名转为IP地址"的过程:
- 网络进程的「DNS线程」接收主进程指令,先查询本地DNS缓存(操作系统缓存 + 浏览器缓存);
- 若本地缓存未命中,DNS线程向DNS服务器发起递归查询:本地DNS → 根DNS → 顶级域DNS → 权威DNS;
- 权威DNS服务器返回域名对应的IP地址,网络进程将IP地址缓存到本地(下次复用),并传递给主进程。
第四步:建立TCP连接(网络进程)
有了IP地址,浏览器就可以和目标服务器建立连接,TCP连接是HTTP请求的基础:
-
网络进程的「TCP线程」通过DNS解析得到的IP地址,与服务器执行「三次握手」,建立TCP连接:
- 第一次:客户端(浏览器)向服务器发送SYN报文,请求建立连接;
- 第二次:服务器向客户端返回SYN+ACK报文,确认收到请求;
- 第三次:客户端向服务器发送ACK报文,确认连接建立。
-
若URL是HTTPS协议,额外执行「TLS/SSL握手」:交换加密密钥、验证服务器证书、建立加密通道(防止数据劫持)。
第五步:发送HTTP请求(网络进程)
TCP连接建立后,网络进程开始向服务器发送HTTP请求,获取页面资源:
-
网络进程的「请求线程」构建HTTP请求报文,包含三部分:
- 请求行:如
GET / HTTP/1.1(请求方法、请求路径、HTTP版本); - 请求头:如
Host: www.baidu.com、User-Agent: Chrome/120.0.0.0、Cookie等; - 请求体:GET请求无请求体,POST请求会包含表单数据或JSON数据。
- 请求行:如
-
通过已建立的TCP连接,将请求报文发送给服务器;
-
服务器接收请求后,处理请求(如查询数据库、生成HTML),并返回HTTP响应报文(状态码、响应头、响应体)。
第六步:接收响应并解析(网络进程 + 浏览器主进程)
网络进程接收服务器响应后,不会直接传递给渲染进程,需要先解析响应内容:
-
网络进程解析响应状态码:
- 若为301/302(重定向):读取响应头中的
Location字段,重新执行第三步(DNS解析)到第五步(发送请求),跳转到新URL; - 若为200(成功):解析响应体(如HTML字节流),并根据响应头的
Content-Type判断资源类型。
- 若为301/302(重定向):读取响应头中的
-
根据
Content-Type分配资源:- 若为
text/html(HTML文件):将HTML字节流传递给渲染进程; - 若为
text/css/application/javascript(CSS/JS文件):暂存资源,后续按需传递给渲染进程; - 若为图片/字体等资源:异步下载,后续传递给渲染进程。
- 若为
-
浏览器主进程收到网络进程的"响应完成"通知后,创建/复用「渲染进程」(每个标签页一个渲染进程),并建立IPC通信通道(主进程↔渲染进程、网络进程↔渲染进程)。
第七步:渲染进程初始化(渲染进程)
渲染进程是页面渲染的核心,初始化阶段主要完成线程启动和通信准备:
-
渲染进程启动后,初始化核心线程:
每个线程的作用可查看这篇文章。
-
渲染进程通过IPC通道,与浏览器主进程、网络进程建立通信,准备接收资源并开始渲染。
第八步:解析HTML构建DOM树(渲染进程 - 渲染主线程)
渲染进程接收HTML字节流后,首先由渲染主线程的HTML解析器处理,构建DOM树。
解析过程中遇到外部资源(<link>/<script>/<img>):
- 通知网络进程异步下载资源,不中断HTML解析(优化速度);
- 遇到无
async/defer的<script>:暂停HTML解析,等待JS下载执行完成后,再恢复解析(因为JS可能修改DOM); - 遇到
<link rel="stylesheet">:异步下载CSS,不中断HTML解析,但会阻塞后续渲染(因为CSSOM未完成,无法生成渲染树)。
关键优化:浏览器有"预解析器"(Preparser),会提前解析后续HTML,发现外部资源并提前通知网络进程下载,减少等待时间。
第九步:解析CSS构建CSSOM树(渲染进程 - 渲染主线程)
HTML解析的同时,网络进程会异步下载CSS资源,下载完成后传递给渲染主线程,由CSS解析器处理,构建「CSSOM树」(CSS对象模型)。
关键细节:CSS阻塞"首次渲染",但不阻塞HTML解析------因为渲染树需要DOM+CSSOM,CSS未完成,无法生成渲染树,页面会白屏。
第十步:渲染树→布局→绘制→合成→GPU渲染(渲染进程 + GPU进程)
第十一步:加载额外资源 + 交互就绪(渲染进程 + 网络进程)
页面首次渲染(首屏显示)后,流程并未结束,还要完成额外资源加载和交互准备:
-
渲染主线程继续解析剩余HTML,网络进程异步下载图片、字体、剩余JS/CSS等资源:
- 图片下载完成后,渲染主线程触发"重绘"(更新图片像素);
- JS下载执行完成后,可能修改DOM/CSSOM,触发"回流/重绘/合成"。
-
渲染进程初始化事件监听(如点击、滚动、输入),JS执行完成后,页面进入"交互就绪"状态;
-
浏览器主进程更新标签页状态(隐藏"加载中"图标,显示页面标题),整个流程结束。
总结
从输入URL到页面加载,本质是浏览器多进程/线程协同工作的过程,核心流程可概括为:
导航阶段(主进程+网络进程):输入URL → 缓存查询 → DNS解析 → TCP连接 → HTTP请求/响应;
渲染阶段(渲染进程+GPU进程):渲染进程初始化 → DOM/CSSOM构建 → 渲染树 → 布局 → 绘制 → 合成 → 屏幕显示;
就绪阶段:加载额外资源 → 事件监听初始化 → 页面交互就绪。