你在地址栏输入一个网址,按下 Enter,页面看起来只是"转了一会儿圈",但浏览器背后其实已经跑完了一条很长的链路。
Mariko Kosaka 在 Chrome 官方文章《Inside look at modern web browser Part 2》里,把这件事拆得非常清楚。看完你会发现:从按下回车到页面真正开始渲染,中间根本不是"发个请求"这么简单。
我把它整理成一个最好记的版本:
前提:
现代浏览器是多进程架构:
• 1 个 浏览器进程(总管:UI、网络、存储、进程调度)
• 多个 渲染进程(每个标签/站点一个)
• 多个 网络线程、UI 线程、存储线程 等
第一关:先判断你输入的到底是什么
浏览器的 UI 线程先看你输入的是:
一个真正的网址
还是一段搜索关键词
也就是说,浏览器第一步不是请求页面,而是先理解你的意图。
第二关:网络线程开始干活
如果确认是 URL,浏览器会发起导航请求。接下来网络线程开始工作:
• DNS 查询
把域名 → IP 地址
有缓存用缓存,没有就走 DNS 服务器查询
• 建立 TCP / TLS 连接
建立可靠传输通道(三次握手)
TLS 握手(HTTPS 才走)
• 协商加密套件
• 验证证书
• 建立加密通道
• 发送 HTTP 请求
• 处理 301 / 302 重定向
如果中间跳转了,浏览器还要重新来一轮。你以为自己只访问了一个地址,浏览器可能已经替你拐了几个弯。
第三关:响应不能直接进渲染进程
这是整篇文章最关键的地方。
响应回来了,浏览器不会立刻把数据塞给渲染进程,而是先过一条"安检链":
1. 看 Content-Type
服务器会先声明:我返回的是 HTML、图片、JSON,还是一个下载文件。
这个信息会直接影响后续路线。比如返回的是 HTML,才可能继续走页面渲染;如果是压缩包,浏览器更可能交给下载管理器。
2. 做 MIME 嗅探
问题是,服务器不一定靠谱。Content-Type 可能缺失,也可能写错。
所以浏览器还会看响应体前几个字节,自己猜一遍这到底是什么内容。这一步就叫 MIME sniffing。
也就是说,浏览器不会完全相信服务器,它会自己再验证一次。
3. 做 SafeBrowsing 检查
接着浏览器会检查这个站点或响应数据是不是命中了恶意站点名单。
如果有风险,浏览器会直接拦下来,显示警告页,而不是继续往下渲染。
4. 做 CORB 检查
CORB 全称是 Cross-Origin Read Blocking,你可以先把它理解成:别让不该进来的跨站敏感数据,流进渲染进程。
比如某些 HTML、XML、JSON 数据,本来就不是给当前页面读的。如果让它们错误地进入渲染进程,就可能带来安全风险。
所以这里的逻辑不是"拿到数据就行",而是先判断这份数据有没有资格进场。
第四关:找一个合适的渲染进程
数据通过检查后,浏览器才开始找渲染进程。
为了提速,Chrome 甚至可能在请求发出去时,就提前准备好一个渲染进程等着。如果后面发现跳到了另一个站点,这个预备进程可能又要换掉。
这也是现代浏览器快的原因之一:很多事情不是线性执行,而是能并行就并行。
第五关:提交导航
当数据和渲染进程都准备好了,浏览器进程会通过 IPC 把这次导航正式提交给渲染进程。
到这一步,才算真正进入"页面开始加载和渲染"的阶段。
也就是说,按下 Enter,不是页面立刻开始渲染;而是浏览器先完成一整套路由、校验、分发,再决定交给谁渲染。
还有两个容易忽略的点
跨站导航可能会换进程
如果你是从 A 站跳到 B 站,Chrome 往往会启用新的渲染进程。这背后和站点隔离、安全边界都有关系。
Service Worker 会改写导航路径
如果当前站点注册了 Service Worker,它就像一个网络代理。浏览器可能先把请求交给它决定:走缓存,还是走网络。
为了不让这个过程拖慢速度,Chrome 还做了 Navigation Preload,也就是在启动 Service Worker 的同时,先把网络请求并行发出去。
前端为什么要关心这件事?
因为这篇文章会帮你真正理解三件事:
为什么 Content-Type 不能乱写 —— 它决定了浏览器怎么路由响应
为什么有些跨域数据明明请求到了,却还是读不到 —— 中间可能被 CORB 拦了
为什么浏览器性能优化,本质上常常是调度优化 —— 提前启动、并行处理、减少等待
很多时候我们讨论前端,只盯着框架和组件。但浏览器真正强大的地方,是它在你看不见的地方,替你做了大量判断。
页面能显示出来,从来不是"请求成功"这么简单,而是一整套现代浏览器工程能力的结果。
参考原文:Mariko Kosaka, Inside look at modern web browser Part 2(Chrome for Developers)