浏览器访问网页全流程:小白友好版详解

浏览器访问网页全流程:小白友好版详解

1. 输入网址:从"网址"到"网络请求"的起点

  • 你要做的事 :在浏览器地址栏输入网址(比如https://www.baidu.com ),按回车。
  • 浏览器的"小心思"
    浏览器首先会检查你输入的是不是"网址"(URL),比如有没有http://https://。如果没有,它可能会自动补全(比如你输入baidu.com ,它会默认加https://)。
    接着,浏览器会启动一个"网络请求线程"------你可以理解为浏览器派了一个"快递员",负责把你的请求送出去,并把网页"包裹"取回来。
    类比:你在购物APP上输入商品名称,APP会启动一个"订单处理员"帮你下单。

2. 找服务器:DNS查询------给"网址"找个"门牌号"

  • 核心问题 :网址是给人看的(比如baidu.com ),但电脑只认"IP地址"(类似服务器的"门牌号",比如14.215.177.38)。浏览器需要通过DNS查询把网址翻译成IP地址。

  • DNS查询的"快递路线" (从近到远找,节省时间):

    1. 浏览器缓存 :浏览器记不记得最近查过这个网址?(比如你刚访问过baidu.com ,浏览器暂时存了它的IP)。
    2. 本机缓存:你的电脑有没有存?(比如操作系统自己记了一些常用网址的IP)。
    3. hosts文件:一个特殊文件,相当于"本地通讯录",可以手动写死网址和IP的对应关系(一般不用管)。
    4. 路由器缓存:家里的路由器有没有存?(路由器帮全家设备查过的网址,可能会暂时记住)。
    5. ISP DNS缓存:你的网络服务商(比如联通、电信)的"DNS服务器"有没有存?(这是专业的"地址簿",存了海量网址的IP)。
    6. DNS递归查询 :如果以上都没有,ISP的DNS服务器会帮你去"根服务器"(全球只有13台!)一层层查,直到找到对应的IP。
      类比:你不知道"XX超市"的地址,先问家人(浏览器缓存),再查手机备忘录(本机缓存),再问小区保安(路由器),最后问114查号台(ISP DNS),直到找到地址。

3. 建立连接:TCP三次握手------"喂,你在吗?我能发东西吗?"

  • 核心问题 :找到IP地址后,浏览器需要和服务器建立"可靠的连接",才能开始传数据。这个过程叫TCP三次握手,确保双方都能正常收发消息。

  • 三次握手"对话" (想象你和服务器打电话确认信号):

    1. 客户端(你) :"喂,服务器,我能给你发数据吗?"(发一个SYN=1的包,相当于"请求连接")。
    2. 服务器 :"收到!我能收到你,你也能收到我吗?"(回一个SYN=1, ACK=客户端序号+1的包,相当于"确认收到,并反问你")。
    3. 客户端(你) :"收到!我也能收到你,开始发吧!"(发一个ACK=服务器序号+1的包,相当于"确认可以开始")。
      为什么要三次? 防止"过时的连接请求"干扰。比如你发了一个请求,但网络延迟,服务器很久才收到,此时你可能已经不想连接了,但服务器以为你要连,就会浪费资源。三次握手能确保双方都是"当前在线且愿意连接"的。
      类比:打电话时,你说"喂?"(1次),对方说"喂,能听到吗?"(2次),你说"能听到,开始说吧"(3次),确认双方都能正常通话。

4. 发请求:HTTP请求------"我想要这个网页,请给我!"

  • 连接建立后 ,浏览器(客户端)会通过TCP连接给服务器发一个HTTP请求报文(相当于"订单详情")。

  • HTTP请求报文的"快递单"内容

    • 请求行 :方法(一般是GET,表示"获取资源")、网址路径(比如/index.html )、HTTP版本(比如HTTP/1.1)。
    • 请求头 :附加信息,比如"我是Chrome浏览器"(User-Agent: Chrome)、"我能接受gzip压缩的内容"(Accept-Encoding: gzip)、"我有没有缓存过这个网页"(If-Modified-SinceIf-None-Match,后面讲缓存会细说)。
    • 请求体 :如果是提交数据(比如登录表单),这里会放数据;如果是GET请求,这里为空。
      类比:你给超市发订单,写着"买1瓶可乐(请求行),我用的是XX快递(请求头),地址是XXX(请求体)"。

5. 服务器处理请求:从"接收订单"到"准备包裹"

  • 服务器收到请求后,会做几件事:

    1. 解析请求 :服务器的"前台"(比如Nginx、Apache)先看请求头里的Host字段(比如www.baidu.com ),判断你要访问哪个"虚拟主机"(一个服务器可能同时放多个网站,比如baidu.comtieba.baidu.com )。
    2. 缓存验证 :服务器会检查请求头里的缓存信息(比如If-Modified-Since):"这个网页客户端是不是已经缓存过了?如果没过期,就不用重发了,让它用自己的缓存吧。"如果缓存有效,服务器会返回304状态码("网页没变化,用你自己的缓存吧")。
    3. 处理业务 :如果需要新的网页,服务器会让"后台程序"(比如Java、Python代码)处理,可能需要查数据库(比如"用户信息""商品列表"),然后生成HTML、CSS、JS等内容。
      类比:超市收到订单后,先看你是不是会员(Host),再看你要的商品是不是刚买过且没过期(缓存验证),如果需要新商品,就去仓库(数据库)拿货,打包成包裹(HTTP响应)。

6. 收响应:HTTP响应------"你的网页包裹到了!"

  • 服务器把网页内容打包成HTTP响应报文**,通过TCP连接发回给浏览器。响应报文包含:

    • 状态码 :服务器的"回复",比如200 OK(成功)、404 Not Found(网页不存在)、500 Internal Server Error(服务器出错了)。
    • 响应头 :比如"内容类型是HTML"(Content-Type: text/html)、"内容大小是10KB"(Content-Length: 10240)、"缓存有效期是1小时"(Cache-Control: max-age=3600)。
    • 响应体 :网页的实际内容,比如HTML代码、图片二进制数据等。
      类比:超市把可乐(响应体)装进盒子,贴上面单(响应头:"易碎品""保质期1小时"),写上"发货成功"(状态码200),然后让快递员送回你家。

7. 关闭连接:TCP四次挥手------"东西收到了,再见!"

  • 数据传完后 ,如果浏览器和服务器不再需要通信,就会关闭TCP连接,这个过程叫四次挥手

  • 四次挥手"对话" (比三次握手多一次,确保双方都发完数据):

    1. 主动方(比如浏览器) :"我说完了,你还有要说的吗?"(发FIN=1,表示"我要关闭发送通道了")。
    2. 被动方(服务器) :"收到,我知道你说完了,但我可能还有数据没发完,等我一下。"(发ACK确认)。
    3. 被动方(服务器) :"我也说完了,你收到了吗?"(发FIN=1,表示"我也关闭发送通道了")。
    4. 主动方(浏览器) :"收到,再见!"(发ACK确认,双方关闭连接)。
      类比:打电话结束时,你说"我没话说了"(1次),对方说"好的,我知道了,你等我说完最后一句"(2次),对方说"我也说完了"(3次),你说"好,挂了"(4次)。

8. 缓存:"这次的包裹先存着,下次直接用!"

  • 缓存的作用:如果网页内容没变,浏览器不用每次都去服务器下载,直接用本地缓存,能节省时间和流量。

  • 缓存怎么判断"要不要用"? 服务器在响应头里会告诉浏览器:

    • Expires (HTTP 1.0):一个绝对时间,比如Expires: 2024-01-01 12:00:00,表示"2024年1月1日12点前,缓存有效,直接用"。
    • Cache-Control: max-age=3600(HTTP 1.1,更常用):相对时间,"从现在开始1小时内(3600秒),缓存有效"。
    • 如果缓存过期了 :浏览器会发请求给服务器"验证缓存",比如带If-Modified-Since("这个网页最后修改时间是不是比我缓存的新?"),如果服务器说"没变",就返回304状态码,浏览器继续用缓存;如果变了,就返回新内容(200状态码)。
      类比:你买了一瓶可乐没喝完,放进冰箱(缓存),下次想喝直接拿,不用再去超市买。

9. 解析渲染:把"代码"变成"网页"------浏览器的"魔法时刻"

  • 浏览器拿到响应体(HTML/CSS/JS代码)后,需要把代码变成你看到的网页,这个过程叫"解析渲染",分几步:

    1. 构建DOM树 :HTML代码是"标签嵌套"的(比如<html><body><p>你好</p></body></html>),浏览器会把标签解析成"树状结构"(DOM树),每个标签是一个节点,方便后续操作。

      • 类比:把"宜家家具说明书"(HTML代码)拆解成"零件列表"(DOM节点)。
    2. 构建CSSOM树 :CSS代码(比如p { color: red; font-size: 16px; })会被解析成"CSS规则树"(CSSOM),记录每个标签的样式。

      • 类比:把"给零件上色的说明"(CSS代码)整理成"每个零件的颜色和大小表"(CSSOM)。
    3. 构建渲染树(Render Tree) :把DOM树和CSSOM树合并,只保留"可见节点"(比如<script>标签、display: none的元素不会显示,就不进渲染树),并计算每个节点的位置、大小、颜色。

      • 类比:把"零件列表"和"上色说明"合并,得到"最终组装图"(渲染树),明确每个零件的位置和样子。
    4. 布局(Layout) :计算每个节点在屏幕上的精确位置(比如"这个段落左上角在(100px, 200px),宽200px,高50px")。

    5. 绘制(Painting) :根据渲染树和布局结果,把像素画到屏幕上(比如给文字上色、画边框、显示图片)。

    6. 复合(Composite) :如果页面有多层(比如固定在顶部的导航栏、滚动的内容区),浏览器会把不同层的绘制结果合并,最终显示完整网页。

10. JS解析:让网页"动起来"的"脚本"

  • HTML解析时遇到<script>标签 ,浏览器会暂停HTML解析,转而去解析JS代码------因为JS可能会修改DOM(比如document.write() )或CSS(比如element.style.color = 'red'),如果不暂停,可能会导致渲染错误。

  • JS解析的"三步曲"

    1. 词法分析 :把JS代码拆成"单词"(比如var a = 1拆成vara=1)。
    2. 语法分析 :把"单词"组成"语法树"(比如判断var a = 1是不是合法的JS语法)。
    3. 执行:JS引擎(比如Chrome的V8引擎)会创建"执行上下文"(记录变量、函数、作用域等),然后一行行执行代码。
  • JS执行的"小细节"

    • 同步脚本 (没有async/defer):会阻塞HTML解析,必须等JS下载+执行完,才能继续解析HTML。
    • 异步脚本(async :下载时不阻塞HTML解析,下载完后立刻执行(顺序不确定,谁先下载完谁先执行)。
    • 延迟脚本(defer :下载时不阻塞HTML解析,等HTML解析完后,按代码顺序执行(适合需要操作DOM的脚本)。
      类比 :你在拼乐高(HTML解析),突然发现说明书里夹了一张"补充说明"(JS代码),你必须先看完补充说明(解析JS),才能继续拼(解析HTML)。如果补充说明是"先放一边,等拼完主体再看"(defer),就可以先继续拼主体。

11. 页面显示:"逐步渲染"------看到的网页不是"一下子"出来的

  • 浏览器解析HTML时是"边解析边渲染"的 :比如解析到<p>你好</p>,就会立刻把这个段落画到屏幕上,不用等整个HTML都解析完。这就是为什么有些网页加载时,你会看到内容"一点点出来"。

  • 两个重要事件

    • DOMContentLoaded:HTML解析完,DOM树构建完成(此时JS可能还没执行完,图片可能还没加载完)。
    • load:所有资源(HTML、CSS、JS、图片、视频等)都加载完,网页完全显示。

总结:从输入网址到看到网页的"全流程"

  1. 输入网址 → 浏览器启动网络线程。
  2. DNS查询 → 把网址翻译成IP地址。
  3. TCP三次握手 → 和服务器建立可靠连接。
  4. 发HTTP请求 → 告诉服务器"我要什么网页"。
  5. 服务器处理 → 生成HTTP响应(网页内容)。
  6. 收HTTP响应 → 浏览器拿到网页代码。
  7. TCP四次挥手 → 关闭连接(如果不需要继续通信)。
  8. 缓存 → 保存网页,下次直接用(如果没过期)。
  9. 解析渲染 → HTML→DOM树,CSS→CSSOM树→渲染树→布局→绘制→显示网页。
  10. JS解析执行 → 让网页交互、动态变化。

整个过程就像"你点外卖":输入菜名(网址)→ 平台查餐厅地址(DNS)→ 骑手联系餐厅(三次握手)→ 下单(HTTP请求)→ 餐厅做菜(服务器处理)→ 骑手送餐(HTTP响应)→ 骑手确认收货后离开(四次挥手)→ 你打开外卖(解析渲染)→ 吃到嘴里(看到网页)。

相关推荐
TimelessHaze13 分钟前
拆解字节面试题:async/await 到底是什么?底层实现 + 最佳实践全解析
前端·javascript·trae
执键行天涯43 分钟前
从双重检查锁定的设计意图、锁的作用、第一次检查提升性能的原理三个角度,详细拆解单例模式的逻辑
java·前端·github
青青子衿越1 小时前
微信小程序web-view嵌套H5,小程序与H5通信
前端·微信小程序·小程序
OpenTiny社区1 小时前
TinyEngine 2.8版本正式发布:AI能力、区块管理、Docker部署一键强化,迈向智能时代!
前端·vue.js·低代码
程序员江鸟1 小时前
Java面试实战系列【JVM篇】- JVM内存结构与运行时数据区详解(私有区域)
java·jvm·面试
qfZYG1 小时前
Trae 编辑器在 Python 环境缺少 Pylance,怎么解决
前端·vue.js·编辑器
bug爱好者1 小时前
Vue3 基于Element Plus 的el-input,封装一个数字输入框组件
前端·javascript
Silence_xl1 小时前
RACSignal实现原理
前端
柯南二号1 小时前
【大前端】实现一个前端埋点SDK,并封装成NPM包
前端·arcgis·npm
dangkei1 小时前
【Wrangler(Cloudflare 的官方 CLI)和 npm/npx 的区别一次讲清】
前端·jvm·npm