当在地址栏输入一个 URL 后,会发生什么,分别被哪些流程处理?
从 Browser Process 接收事件开始
一个 Browser Process 内部有三个主要工作的线程
- UI Thread:处理整个浏览器除 Dom 外的其他区域 UI 交换和事件。
- Network Thread:处理由整个浏览器发出的网络请求
- Storage Thread: 存储线程:控制本地相关文件的访问等。
一次 url 输入的流程大致如下:
- Browser 进程接管,并交给 UI 线程处理
- UI 线程接收到浏览器 输入框的内存。
- 判断是 google 搜索内容
- 还是 一个 URL,请求资源的定位符
- 浏览器 tab 开始转菊花,表示加载开始
- 对于 URL ,UI 线程创建一个 network 任务,准备请求一个网络请求内容。
- 然后 Network Thread 开始接管这个网络请求任务:
- 解析 DNS
- 建立 TLS 安全链接,发起请求
- 开始读取 Response 内容,分析 HEAD 和 Body (payload: 二进制载荷数据)
- 根据 Header 中的 ‘Content-Type’ 来解析二进制的 payload 数据。
- 跨域内容检查,安全控制 CSP 等。
- 如果是其他文件,例如 zip,则交给 下载管理器,去下载文件。
- 如果是 HTML 内容,Network Thread 的一切检查都合法的情况下,Network Thread 会把内容回调给 UI Thread。
- 然后 UI Thread 在去启动或者使用一个已有的 Render Process 去渲染 DOM。
- 一般为了优化渲染速度,UI Thread 会再发送请求给 Network Thread 的同时,就并行(发)的开始或者找到一个可用的 Render Process。这样数据请求完成后,可以直接开始渲染。不需要等待启动渲染进程的完成。
- 数据通过 IPC 从 Browser Process 发给 Render Process。
DOM loading 阶段 (commit navigation)
一旦 Browser 进程已经确认:Render 进程开始处理相关的渲染工作。Browser 进程就会停止 tab 的菊花旋转,然后记录一个 history 栈 (back/forward)。准备好接受 Render Process 的结果。
卸载前 beforeunload
event
如果整个过程中,用户再次输入重新定位到其他 URL,那么浏览器把上述流程重新做一遍,但是在这之前,会检查是否有
beforeunload
事件,如果有,则处理完成后,再进行下一轮处理和跳转。- 这是一个生命周期钩子函数,开发者可以注册:
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 共同工作。
- 如果Service Worker 判断也需要进行网络请求 (过期或者其他)
- 那么直接使用刚刚已经发起的网络请求结果
- 这样达到最大的并行能力,节省时间。
