一、浏览器的架构
介绍
单进程架构下,由于线程崩溃导致浏览器整个崩溃的问题无法解决,因此现在一般采用chormium的多进程架构
- 一个浏览器进程,流程控制,进行进程间的通信
- 一个网络进程,进行网络请求的提交
- 一个GPU进程,开启硬件加速
- 多个渲染进程,一般为每个页面开启一个渲染进程
- 多个插件进程,当使用插件时开启
问题
(1) 打开一个页面一般几个进程
打开一个页面一般四个进程,浏览器进程、网络进程、GPU进程和一个渲染进程,特殊情况下还会开启插件进程
(2) 为什么一个页面崩掉,其他页面一般无影响
页面崩掉的是由于当前页面对应的渲染进程崩溃掉,但是由于浏览器多个渲染进程之间一般是没有联系的,所以只要浏览器进程存在,其他页面不受影响,增加了浏览器的稳定性
(3) 为什么有的时候一个页面崩掉会影响其他页面
通常情况下是一个页面使用一个进程,但是,有一种情况,叫"同一站点(same-site)",具体地讲,我们将“同一站点”定义为根域名(例如,xxx.com)加上协议(例如,https:// 或者http://),还包含了该根域名下的所有子域名和不同的端口,如以下:
这种情况下,如果从当前页面打开另外的页面,如果这两个页面属于同一站点的话,浏览器会将渲染进程复用,即两个页面共同使用同一个渲染进程,所以一个页面崩溃会导致使用同一个渲染进程的页面都崩溃掉
二、 建立连接获取资源
过程
-
浏览器进程根据用户输入,向网络进程提交请求
-
网络进程首先查看是否有对应可用缓存
- 如果有,则进行网络请求的拦截,将资源返回并设置状态码为304
- 如果没有,则进行网络请求
- 首先进行DNS域名解析,获得对应的ip地址
- 根据ip地址,建立tcp连接
- 发送http请求,由于http/1.1 是支持长连接的,所以我们可以发起多个http请求
- 如果存在重定向,则需要重新执行2.1-2.3的过程
-
处理请求的资源,进行页面的渲染
问题
(1) 不同层的作用
- http层 生成针对目标web服务器的http请求报文
- tcp层,建立连接,将请求分割为报文段,通过慢启动+拥塞避免、快重传+快恢复进行可靠传输
- ip层,根据目标ip地址,进行数据包的中转和传送
(2) 为什么要采用进程间通信的方式,将网络请求和渲染部分分离开?
网络资源通过网络进程下载下来,然后通过IPC提交给渲染进程。整个过程我们认为网络资源是不安全的,如果我们 将权限全部交给渲染进程,一旦恶意资源被执行,就可能通过这个方式控制操作系统,所以我们需要在操作系统和渲染进程之间建立一道墙进行保护——安全沙箱。
安全沙箱最小的保护单位是进程,并且能限制进程对操作系统资源的访问和修改,这就意味着如果要让安全沙箱应用在某个进程上,那么这个进程必须没有读写操作系统的功能,比如读写本地文件、发起网络请求、调用 GPU 接口等。
所以对应的我们只让渲染进程进行对文档的解析和渲染,但是文件、请求、存储等交给浏览器内核,这样就建立了安全沙箱,使得渲染进程使用操作系统功能,只能通过IPC通信才能完成,增加了浏览器的安全性。
(3) 为什么图片要通过浏览器内核进行展示,而不是通过渲染进程进行展示 ,渲染进程只进行生成图片
渲染进程需要渲染出位图,将图片通过IPC交由浏览器内核进行渲染展示。操作系统将输入事件传递给浏览器内核,经由浏览器内核对输入事件进行分发,限制了渲染进程监听用户输入功能的能力。
三、渲染页面
整体过程
- 渲染进程对HTML进行解析,生成DOM树
- 渲染进程将CSS样式表生成对应的CSSOM树,计算出对应的DOM节点的style
- 创建布局树,计算元素信息
- 对布局树,进行分层绘制
- 将图层分成块,进行光栅化转成位图 【通常,栅格化过程都会使用 GPU 来加速生成,使用 GPU 生成位图的过程叫快速栅格化,或者 GPU 栅格化,生成的位图被保存在 GPU 内存中。】
- 合成线程发送绘制图块命令 DrawQuad 给浏览器进程 【这一步由第二部分可知,我们需要进行IPC】
- 浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上
问题
(1) 为什么把js放在html文档下边
由于渲染进程中存在GUI渲染线程和js引擎线程,GUI负责界面的绘制,js负责交互逻辑,所以当解析html文档时,如果遇到js代码,会切换线程,此时html的解析会停止,直到js加载完成,如果js非常大,会造成页面卡顿假死的情况,极大的影响用户体验。
所以一般将js放在body后。当然也存在js不阻塞的解析的情况,即在js标签上增加defer字段,标识可以与dom渲染并行处理,或者增加async 进行异步处理(下载完成立刻执行)
(2) css为什么要放在head标签中
因为将CSS放在head中,可以提前构建CSSOM树,确定每个DOM节点的style信息,这样当解析到某个DOM节点时,即可知道他的style,解析完DOM节点后即可 Render Tree。【一次render】
如果将CSS放在body尾部,解析完DOM后,网页即会Render Tree,还需要再解析CSSOM,然后再对DOM进行style的更新,再进行一次Render Tree,即产生了reflow,产生性能问题。【两次render 造成reflow】