浏览器
以 Google Chrome 为例,chrome 是一个多进程架构
浏览器进程
- 浏览器进程。主要负责处理浏览器的界面交互、子进程管理、存储等功能
- 渲染进程
- GUI 渲染线程
- js 引擎线程(和 GUI 互斥)
- 定时器触发线程
- 事件触发线程
- 异步 http 请求线程
- IO 线程
- ...
- GPU 进程。绘制 UI 界面
- 网络请求进程。处理页面网络请求和加载资源
- 插件进程
出于安全考虑,渲染进程和插件进程都是运行在沙箱模式下
需要注意的是,这些进程中,浏览器主进程、网络进程、GPU 进程都是所有 Tab 共用的
五层网络协议体系结构
- 应用层
- 传输层
- 网络层
- 数据链路层
- 物理层
输入 url 到响应发生了什么
主要流程如下:
- 输入判断。判断输入为 URL 还是搜索内容,如果为 URL,就将 URL 通过 IPC(进程间通信)传给网络请求进程并由它发起请求。
- http 资源缓存检查。
- DNS 解析。解析域名并返回对应的 IP 地址,浏览器会做缓存。(如果是 https,还会建立 TLS 连接)
- TCP 连接。TCP 三次握手
- 发送 HTTP 请求。
- 服务器处理请求并返回响应数据给网络进程。解析响应头时,可能发生重定向。
- 浏览器进程接收到网络进程解析好的响应头数据,向渲染进程 提交文档
- 渲染进程和网络进程建立传输数据的管道
- 等文档数据传输完成,渲染进程会返回 确认提交 的消息给浏览器进程
- 浏览器进程收到确认提交的消息,会更新浏览器界面和 web 页面
- 浏览器解析渲染页面。
- 构建 DOM 树
- 样式计算。转换 css 文本为 styleSheets,并转换样式表中的属性值,使其标准化。计算 DOM 树种每个节点的具体样式
- 布局。计算 DOM 树种可见元素的几何位置
- 分层。
- 绘制。
- 栅格化。
- 合成和显示。
- 断开连接。TCP 四次挥手
同一站点:指的是具有相同协议和根域名的网页。如果从一个页面中打开另一个属于相同站点的页面,新页面将复用该页面的渲染进程
更详细内容可以参见 超详细过程
浏览器缓存
当浏览器再次访问一个已经访问过的资源时,它会这样做:
- 看看是否命中强缓存,如果命中,就直接使用缓存
- 如果没有命中强缓存,就发请求到服务器检查是否命中协商缓存
- 如果命中协商缓存,服务器会返回 304 告诉浏览器使用本地缓存
- 否则,返回最新的资源
DNS
从一个域名到一个 IP 地址到底发生了什么?
- 浏览器查询自己的缓存中是否有该域名的访问记录,如果有的话直接访问对应的 IP 地址,否则进行下一步
- 查询本地 host 文件,否则进行下一步
- 进入路由器缓存中查找,以上均为客户端的 DNS 缓存,找不到就进入下一步
- 进入 ISP 的 DNS 缓存中查询,比如电信的 DNS 缓存服务器;否则进入下一步
- 进入根服务器、顶级域名服务器、主域名服务器进行查询,如果没有找到就进入下一级域名服务器查找,并重复该步骤直到找到正确记录
- 本地域名服务器将返回的结果保存到缓存中,客户端通过这个 IP 地址与 web 服务器建立链接。
浏览器渲染页面
- 浏览器获取 HTML 文件,然后对文件进行解析,形成 DOM Tree
- 与此同时,进行 CSS 解析,生成 Style Rules
- 接着将 DOM Tree 与 Style Rules 合成为 Render Tree
- 接着进入布局(Layout)阶段,也就是为每个节点分配一个应出现在屏幕上的确切坐标
- 随后调用 GPU 进行绘制(Paint),遍历 Render Tree 的节点,并将元素呈现出来
回流(Reflow)和重绘(Repaint)
- 回流是指页面中某些元素发生变化而影响了布局时(如尺寸、位置改变),浏览器需要重新布局并绘制的过程。
- 重绘是指页面中某些元素发生了不影响布局的变化时(如颜色改变),浏览器重新绘制的过程。
- 回流一定会包括重绘,所以回流会更影响性能,在实际操作中,要尽量减少回流。