当在地址栏输入一个 URL 后,会发生什么,分别被哪些流程处理?

从 Browser Process 接收事件开始

一个 Browser Process 内部有三个主要工作的线程

  1. UI Thread:处理整个浏览器除 Dom 外的其他区域 UI 交换和事件。
  2. Network Thread:处理由整个浏览器发出的网络请求
  3. Storage Thread: 存储线程:控制本地相关文件的访问等。

一次 url 输入的流程大致如下:

  1. Browser 进程接管,并交给 UI 线程处理
  2. UI 线程接收到浏览器 输入框的内存。
  3. 对于 URL ,UI 线程创建一个 network 任务,准备请求一个网络请求内容。
  4. 然后 Network Thread 开始接管这个网络请求任务:
  5. 如果是其他文件,例如 zip,则交给 下载管理器,去下载文件。
  6. 如果是 HTML 内容,Network Thread 的一切检查都合法的情况下,Network Thread 会把内容回调给 UI Thread。
  7. 然后 UI Thread 在去启动或者使用一个已有的 Render Process 去渲染 DOM。

DOM loading 阶段 (commit navigation)

一旦 Browser 进程已经确认:Render 进程开始处理相关的渲染工作。Browser 进程就会停止 tab 的菊花旋转,然后记录一个 history 栈 (back/forward)。准备好接受 Render Process 的结果。

卸载前 beforeunload event

如果整个过程中,用户再次输入重新定位到其他 URL,那么浏览器把上述流程重新做一遍,但是在这之前,会检查是否有 beforeunload 事件,如果有,则处理完成后,再进行下一轮处理和跳转。

  • 这是一个生命周期钩子函数,开发者可以注册:
glsl
window.addEventListener('beforeunload', (event) => {
  event.preventDefault(); // 很关键
  event.returnValue = ''; // 有些浏览器需要这样设置
});

相当于浏览器在卸载当前页面的最后一步的回调,给用户一些重要提示等。

  • 这是一个同步事件,里边如果注册了异步任务,不会被处理。

Service Worker

一般一个 tab 会有一个独立的渲染进程 (Render Process),负责 DOM 树、CSS、JS 执行和绘制等。所以一般情况,Service Worker 的注册 (JS 代码) 都是在渲染进程进行的。

那么 Browser Process 如何知道是否有 Service Worker 被注册了呢:通过 URL 注册域检查。

  • 每个 Service Worker 是绑定在一个 URL 上的
  • 浏览器进程的 Network Thread 会先检查某个请求是否有 Service Worker 注册,如果有。
  • 浏览器进程的 UI 线程让对应的渲染进程去执行这个 service worker 来返回网络请求数据。
  • 事实上,与此同时,UI Thread 也会同时发起一个网络请求,让它和 Service Worker 共同工作。