🎓 作者简介: 前端领域优质创作者
🚪 资源导航: 传送门=>
🎬 个人主页: 江城开朗的豌豆
🌐 个人网站: 江城开朗的豌豆 🌍
📧 个人邮箱: YANG_TAO_WEB@163.com 📩
💬 个人微信: y_t_t_t_ 📱
📌 座 右 铭: 生活就像心电图,一帆风顺就证明你挂了。 💔
👥 QQ群: 906392632 (前端技术交流群) 💬
大家好,我是[小杨],今天我们来聊聊一个看似简单却暗藏玄机的问题:当我在浏览器地址栏输入一个网址并按下回车后,到底发生了什么? 这个过程看似瞬间完成,实际上浏览器在背后默默执行了十几个关键步骤。作为前端开发者,理解这个过程对性能优化和问题排查都很有帮助。
1. 整体流程概览
先来看下完整流程的简化版:
- 输入URL并回车
- DNS解析:把域名变成IP地址
- 建立TCP连接:和服务器三次握手
- 发送HTTP请求
- 服务器处理请求并返回响应
- 浏览器解析渲染页面
- 连接关闭(如果是HTTP/1.1可能会保持连接)
下面我们拆解每个环节,用通俗易懂的方式讲清楚。
2. 详细步骤解析
2.1 第一步:URL解析
当我在地址栏输入 https://www.example.com
并回车时,浏览器首先会:
- 检查输入的内容是URL还是搜索关键词
- 如果是URL,判断协议(
http
/https
)是否完整,不完整会自动补全 - 对特殊字符进行编码处理(比如空格变成
%20
)
2.2 第二步:DNS域名解析
浏览器不能直接通过域名找到服务器,需要先转换成IP地址:
- 查浏览器缓存:看之前是否访问过这个网站
- 查系统缓存(如Mac的
/etc/hosts
文件) - 查路由器缓存
- 问ISP的DNS服务器(比如电信/联通的DNS)
- 如果还是找不到,会进行递归查询直到根域名服务器
// 类似这样的DNS查询过程(伪代码)
function findIP(domain) {
if (浏览器缓存有domain) return 缓存IP;
if (系统hosts文件有记录) return hosts中的IP;
向本地DNS服务器查询();
if (本地DNS服务器有记录) return 结果;
向更高级DNS服务器递归查询();
return 最终IP;
}
2.3 第三步:建立TCP连接
拿到IP后,浏览器要通过三次握手和服务器建立TCP连接:
- 浏览器 → 服务器:发送SYN=1(同步)报文
- 服务器 → 浏览器:回复SYN=1, ACK=1(确认)
- 浏览器 → 服务器:发送ACK=1
# 三次握手示意图
浏览器 服务器
|----SYN---->|
|<--SYN+ACK--|
|----ACK---->|
如果是HTTPS,还会额外进行TLS握手(交换密钥、验证证书等)。
2.4 第四步:发送HTTP请求
TCP连接建立后,浏览器发送真正的HTTP请求:
GET / HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html
Cookie: name=我
这个请求头包含了:
- 请求方法(GET/POST等)
- 需要的资源路径(
/
表示首页) - 浏览器信息(User-Agent)
- 支持的压缩格式(Accept-Encoding)
- 携带的Cookie(如果有)
2.5 第五步:服务器处理请求
服务器收到请求后:
- Web服务器(如Nginx)接收请求
- 可能转发给应用服务器(如Node.js/Java)
- 查询数据库获取数据
- 生成HTML响应(或返回JSON等数据)
// 伪代码示例:Node.js处理请求
app.get('/', (req, res) => {
const user = db.query('SELECT * FROM users WHERE name = "我"');
res.render('index', { user });
});
2.6 第六步:浏览器解析渲染
服务器返回HTML后,浏览器开始关键渲染路径:
- 解析HTML → 构建DOM树
- 解析CSS → 构建CSSOM树
- 合并成渲染树
- 布局计算(Layout)
- 绘制(Paint)
graph TD
A[HTML] --> B(DOM树)
C[CSS] --> D(CSSOM树)
B --> E(渲染树)
D --> E
E --> F[布局]
F --> G[绘制]
如果遇到<script>
标签会暂停HTML解析,先执行JS(除非加了async/defer
)。
2.7 第七步:加载其他资源
页面中引用的图片、CSS、JS等会触发额外请求:
<!-- 这些标签都会产生新的HTTP请求 -->
<link rel="stylesheet" href="style.css">
<script src="app.js"></script>
<img src="me.jpg" alt="我">
浏览器会并行下载这些资源(HTTP/1.1有并发限制,HTTP/2可以多路复用)。
3. 性能优化关键点
理解了流程后,我们可以针对性优化:
- 减少DNS查询:使用DNS预加载
<link rel="dns-prefetch">
- 减少TCP连接:使用HTTP/2、合并域名
- 压缩资源:Gzip、Brotli压缩
- 缓存策略:设置
Cache-Control
头 - 减少重绘回流:避免频繁操作DOM
4. 实际案例演示
假设我的个人博客(https://myblog.com
)加载很慢,通过Chrome DevTools分析发现:
- 首次加载耗时2s(主要卡在DNS查询和TCP连接)
- 图片未压缩,多消耗800KB流量
- JS文件阻塞渲染
优化方案:
- 配置DNS预加载
- 启用CDN加速
- 压缩图片为WebP格式
- 给JS添加
defer
属性
优化后加载时间降到800ms!
5. 总结
从输入URL到页面展示,主要经历:
- URL解析 → 2. DNS查询 → 3. TCP握手
- HTTP请求 → 5. 服务器处理 → 6. 渲染解析
理解这个过程后,无论是调试页面加载问题,还是做性能优化,都能更加得心应手。希望这篇文章对你有帮助,如果有疑问欢迎在评论区讨论~