大家好,我是有一点想法的thinkmars,目前在准备面试与工作,借着间隙时间学习复习,写一点基础文章,欢迎想找工作的人与我一起学习,一起讨饭吃~
前言
理解页面加载流程对于性能优化至关重要,前端性能优化无外乎就是优化这个流程。相对底层的协议来说,前端优化的空间比较小,难度较大,而后端服务通信可以选用一些更高效的协议或者自定义协议。前端优化通常集中在建立连接后的阶段,比如缩短传输距离、减少传输次数、减小资源传输体积、降低浏览器渲染压力、使用资源缓存等等。
整个流程大致分为以下步骤:
1. 输入 URL 并解析
- 用户行为 :在浏览器地址栏输入
https://www.example.com
并按下回车。 - 浏览器解析 URL :
- 检查 URL 的协议(
https
)、域名(www.example.com
)、端口(默认443
)、路径(/
)等。 - 如果输入的不是完整的 URL,浏览器会尝试补全(比如自动添加
http://
或搜索关键词)。
- 检查 URL 的协议(
2. DNS 域名解析
- 目的 :将域名(如
www.example.com
)转换成服务器的 IP 地址(如192.0.2.1
)。 - 具体步骤 :
- 浏览器缓存:检查浏览器是否缓存过该域名的 IP。
- 系统缓存:查询本地 hosts 文件或操作系统缓存。
- 路由器缓存:检查路由器 DNS 缓存。
- ISP DNS 服务器:向互联网服务提供商(如电信、联通)的 DNS 服务器发起请求。
- 递归查询 :如果 ISP 的 DNS 没有缓存,会从根域名服务器(
.
)开始逐级查询:- 根域名服务器 →
.com
顶级域名服务器 →example.com
权威域名服务器。
- 根域名服务器 →
- 返回 IP :最终获得
www.example.com
对应的 IP 地址。
graph TD
A[浏览器缓存] --> B[系统缓存]
B --> C[路由器缓存]
C --> D[ISP DNS服务器]
D --> E[根域名服务器]
E --> F[顶级域名服务器]
F --> G[权威域名服务器]
G --> H[返回IP地址]
3. 建立 TCP 连接(三次握手)
- 目的:浏览器和服务器通过 TCP 协议建立可靠连接。
- 三次握手过程 :
- 浏览器 → 服务器 :发送
SYN=1, Seq=x
(同步请求)。 - 服务器 → 浏览器 :回复
SYN=1, ACK=x+1, Seq=y
(确认并同步)。 - 浏览器 → 服务器 :发送
ACK=y+1
(最终确认)。
- 浏览器 → 服务器 :发送
- 结果:连接建立,可以传输数据。
graph LR
A[浏览器] -- SYN=1,Seq=x --> B[服务器]
B -- SYN=1,ACK=x+1,Seq=y --> A
A -- ACK=y+1 --> B
4. 发送 HTTP 请求
-
浏览器构造 HTTP 请求 ,例如:
httpGET / HTTP/1.1 Host: www.example.com User-Agent: Chrome/... Accept: text/html, */*
-
如果是 HTTPS :
- 先进行 TLS 握手(交换密钥、验证证书)。
- 加密后续通信内容。
5. 服务器处理请求
- Web 服务器(如 Nginx/Apache) :
- 解析请求路径,可能转发给后端应用(如 PHP、Node.js)。
- 后端应用 :
- 处理业务逻辑(如查询数据库)。
- 生成 HTML 响应(或 JSON 数据)。
6. 服务器返回 HTTP 响应
-
响应示例:
httpHTTP/1.1 200 OK Content-Type: text/html Content-Length: 1234 <!DOCTYPE html> <html>...</html>
-
状态码 :
200
表示成功,404
表示页面不存在等。
7. 浏览器解析和渲染页面
- 解析 HTML:构建 DOM 树(文档对象模型)。
- 解析 CSS:构建 CSSOM 树(CSS 样式规则)。
- 合并为渲染树 :结合 DOM 和 CSSOM,排除不可见元素(如
<head>
)。 - 布局(Layout):计算每个元素的位置和大小。
- 绘制(Paint):将像素点绘制到屏幕上。
- 执行 JavaScript :
- 如果遇到
<script>
标签,会暂停 HTML 解析,先执行 JS(除非标记为async
或defer
)。
- 如果遇到
graph TD
A[解析HTML] --> B[构建DOM树]
B --> C[解析CSS]
C --> D[构建CSSOM树]
D --> E[合并渲染树]
E --> F[布局计算]
F --> G[绘制页面]
G --> H[执行JavaScript]
H -->|遇到