简单又不简单的 Navigation

2025-09-11 pv

打开浏览器,最常见的操作就是浏览网页。

直接在地址栏输入网址,或在搜索引擎里检索关键字,然后等待浏览器的跳转。

这个过程,就叫作导航(Navigation)。

这是一个于普通用户而言很直观的行为,可是在 Chromium 的内部实现上,远比看上去复杂。不仅涉及到安全校验,网页渲染,还有进程之间的通信,调度等。

从单纯使用的角度,的确没有必要了解这么深入,但从软件架构方面,了解这样一个复杂的过程是如何被简单地呈现,是一个非常好的学习的机会

因此今天这篇文章,打算深入挖掘 Navigation 背后发生的一些事情:如何从点击到显示

1. 什么是 Navigation

Chromium 的文档里讲:

Navigation is one of the main functions of a browser. It is the process through which the user loads documents.

导航是用户加载文档的过程

Web 世界的本质,是链接。链接可能发生在很多地方:

  • 用户点击 <a> 标签,从当前页面跳转到另一个页面
  • 地址栏输入 www.google.com,回车后跳转到给定页面
  • 点击“前进/后退”按钮

可见,与通俗的理解一样,导航就是从本地出发,到达另一个目的地(目标网页)。

2. Navigation 的几个阶段

用户看上去的效果是,点击后,网页迅速呈现。

背后有一系列复杂的流程。

2.1 BeforeUnload

第一个要执行的,就是触发前一个网页的 beforeunload 事件。

这是一种保护机制。因为在导航前,可能前一个网页还有些事情没有处理完,比如用户数据还没有保存,这里的事件回调,给了开发者介入的机会:可以在此时提醒,推迟甚至取消本次导航。

2.2 Network & Response

这是整个 Navigation 最核心的部分。

在发起请求前,Chromium 会做一些校验(Validation),判断请求是否合法,并提供了 NavigationThrottles 对象专门用于观察、推迟、阻止和取消本次导航。

DNS 解析,TCP 握手连接也是发起网络请求前的必备操作。

接着,Chromium 的网络栈(Network Stack)发起 HTTP(S) 请求,拿到服务器返回的响应。

  • 如果是 200,且返回了 HTML/JS/CSS 等内容,就进入下一步
  • 如果是 301/302 重定向,浏览器会更新导航目标地址,并重新发起一次导航
  • 如果是 4xx, 5xx,则是遇到了 HTTP 级别的错误

2.3 Commit

浏览器进程(Browser Process)收到来自网络栈的数据后,根据相应的来源、响应头(Response Headers)和隔离策略(Isolation Policy)选择合适的渲染进程(Render Process),然后将数据提交给它,等待它创建文档后并返回确认(Acknowledgement)。

旧的文档被卸载,新文档被创建。

导航至此结束

2.4 Loading

此时用户还看不到新的页面

因为 Chromium 将整个网页展示的过程解耦为两个阶段:Navigation 和 Loading。

Loading 阶段会继续从服务器读取剩余的返回数据,解析并渲染,执行响应的脚本,加载文档引用的其他资源。

最终呈现新页面。

像 JavaScript 中的 DOMContentLoaded 等事件,就是在该阶段被触发的。

3. 特殊的 Navigation

  • 同一进程内导航(Same-Site Navigation)

    如果目标页面和当前页面属于同一站点(比如都在 example.com),通常可以复用当前渲染进程

  • 跨站点导航(Cross-Site Navigation)

    如果目标页面和当前页面不属于同一站点,Chromium 出于安全考虑会切换到新的渲染进程(Site Isolation)。

  • Back/Forward Cache (BFCache)

    最新的 Chromium 提供了 BFCache 机制,整个页面的完整快照都被缓存(包括 DOM 树、JS 堆内存状态、渲染状态),优化“前进/后退”网页的加载速度

4. 总结

对于前端或浏览器开发者,了解 Navigation 有助于建立一套完整的图景。借此可以:

  • 优化性能:知道何时会触发新的 Navigation,哪里有缓存
  • 理解安全:跨站点的进程隔离策略,以及 Chromium 的多进程通信机制

这是一套完整的、系统的、工业级的解决方案。

想起之前工作汇报的时候,老板通常会提醒我,对于复杂的问题,首先要梳理一个 Big Map 出来,按图索骥,不断填充,流程和思路都会更清晰。

我想很多事情都是这样,先抓主线,从宏观上有整体的认识,对于细节部分,按需地深入

(完)

参考

  1. Chromium Docs - Life of a Navigation🔗
  2. Document: DOMContentLoaded event - Web APIs | MDN🔗
在 GitHub 上编辑本页面

最后更新于: 2025-09-11T01:20:23+08:00