Chrome 出现前的浏览器

  • 采用单进程,所有功能模块分成多个线程都在同一进程中运行。
    • 缺点一:不稳定,一个线程崩溃,整个进程就会挂掉;
    • 缺点二:容易卡,其中一个页面卡住,所有页面都会卡;
    • 缺点三:存在安全隐患,渲染线程/插件线程由于具有较高的权限,当执行某些第三方 JS 脚本时,可能会有恶意代码获取到系统权限而进行读写、窃取数据。

Chrome

  • 多进程架构

  • 每个页面有单独的渲染进程、插件进程,并且将这两个进程都装进“沙箱”中,获取不到系统权限,当需要获取系统权限(读写...)时,需要转交给浏览器主进程进行,进程间通过 IPC 进行通信。

  • chrome 五大进程:

    • 浏览器主进程 - 页面展示、用户交互、管理子进程、提供存储功能
    • 渲染进程 - ==JS V8 引擎、排版引擎 Blink==,将 JS、 HTML、CSS 转为 DOM Tree、Render Tree,负责页面的渲染、布局和绘制
    • 插件进程 - 加载、运行页面的插件
    • 网络进程 - 下载网络资源
    • GPU 进程 - 绘制网页和 UI

Chrome 工作原理

从输入 URL 到页面展示,中间发生了什么?

  1. 浏览器输入栏得到有效的 URL 后,主进程将 URL 交给网络进程;

  2. 网络进程先检查本地是否有缓存资源,若有则返回给浏览器并中断请求,否则进入网络流程:

    • 进行 DNS 解析,
    • 建立 TCP/IP HTTP/TLS 连接,
    • 网络进程构建请求头和请求体,向服务端发送请求,并接受响应数据,
    • 若为重定向响应头 301(永久重定向)、302(临时重定向),则需要根据响应头的 location 字段再次执行请求过程
    • 若响应头为 200 时,则根据响应头的 Content-Type 字段进行响应内容的解析(content-type: application/octet-stream 时,浏览器自动开启下载流程)
  3. 网络进程接受到响应数据后,通知主进程,而主进程视情况开启一个渲染进程(同一协议,同一根域名的站点共用一个渲染进程),

  4. 主进程提交文档给渲染进程,渲染进程与网络进程建立数据连接通道,读取响应体数据,接受完毕后渲染进程返回确认提交给主进程,

  5. 浏览器主进程收到消息后出现白屏,等待渲染进程对页面进行渲染...

怎么才出现白屏......
没想到白屏之前浏览器干了这么多活......

  1. 渲染进程(渲染流程):
    • HTML 解析器 - 构建 DOM Tree - 流式解析
    • 分词器(HTML 解析器内) - 将开始/结束标签识别并分开成为 token
    • token ---> DOM Tree
    • 处理 script 标签:暂停 HTML 解析器 --->将 script 标签中的 JS 交给 JS 引擎解析/引用类型的 script 标签会让网络进程下载并交由 JS 引擎解析 ---> 恢复 HTML 解析器。
    • chrome 做出了预解析优化,渲染进程收到网络进程的字节流时,会开启一个预解析线程,解析到引用的 JS、CSS 后会提前进行下载。
    • 处理 CSS 样式:styleSheets 转化、CSS 标准化
    • DOM + CSSOM = Render Tree
    • 生成 Render Tree 的过程就是在进行布局计算,计算元素的位置,然后分层、计算绘制列表(记录绘制命令的顺序 ~= 图层的顺序)
    • 渲染进程在主线程中完成上述操作,然后将绘制列表交给合成线程合成线程将每个图层划分为图块(256 x 256 || 512 x 512),并且将视口区域的图块优先转为位图。
    • 每个图块在栅格化线程池中通过 GPU 加速在 GPU 进程中生成位图,一旦所有图块都被栅格化生成,合成线程就会向主进程发送绘制图块的命令,主进程收到后将生成的页面内容绘制到内存,最后将内存中的页面绘制到屏幕上。

参考:浏览器工作原理入门