
也许每个前端工程师都想了解浏览器的工作原理.
我们想知道从从浏览器地址栏中输入URL到显示页面仅几秒钟之内浏览器的作用;
我们希望了解为什么我经常听到的各种代码优化解决方案可以发挥最佳作用;
我们想更详细地了解浏览器的渲染过程.
一个好的程序通常分为几个独立且相互协调的模块. 浏览器也是如此. 以Chrome为例. 它由多个过程组成. 每个过程都有自己的核心职责. 他们彼此互动. 与浏览器的整体功能配合,每个进程包含多个线程,一个进程内的多个线程也将协同工作以完成该进程的职责.
对于一些前端开发的学生来说,过程和线程的概念可能有点含糊. 为了更好地了解浏览器的多进程体系结构,在这里我们简要讨论进程和线程.
进程和线程
流程就像是有边界的生产工厂,线程就像个人员工在工厂里可以做自己的事情或互相合作做同样的事情.
当我们启动一个应用程序时,计算机将创建一个进程,操作系统将为该进程分配一部分内存,该应用程序的所有状态将存储在此内存中,该应用程序还可能创建多个线程为了协助工作,这些线程可以共享此内存中的数据. 如果应用程序关闭,则该过程将终止,并且操作系统将释放相关的内存. 更加生动的图表如下:
进程和线程
一个进程还可以要求操作系统派生另一个进程来执行不同的任务. 系统将为新进程分配独立的内存,并且两个进程可以使用IPC(进程间通信)进行通信. 许多应用程序将采用这种设计. 如果工作进程无响应,则重新启动此进程不会影响其他应用程序的工作.
通过IPC进行进程间通信
如果对进程和线程的理解有疑问,可以参考以下文章.
进程和线程的简单解释-阮一峰的网络日志. 
浏览器体系结构
基于上述知识,我们可以更合理地讨论浏览器体系结构. 实际上,如果要开发浏览器,它可以是单进程多线程应用程序,也可以是使用IPC通信的多进程. 应用.
不同浏览器的架构模型
不同的浏览器使用不同的架构模式. 这里没有标准. 本文以Chrome为例:
Chrome使用多进程体系结构,在顶层使用“浏览器”进程来协调浏览器的其他进程.
Chrome浏览器的不同进程
具体来说,Chrome的主要流程及其职责如下:
负责包括地址栏,书签栏,前进和后退按钮等;负责处理浏览器的一些不可见的底层操作,例如网络请求和文件访问;负责控制选项卡中有关网页渲染的所有内容. 网页中使用的所有插件(例如Flash)均负责GPU相关任务
不同的过程负责浏览器区域图
Chrome还为我们提供了一个“任务管理器”,使我们可以方便地查看当前浏览器中正在运行的所有进程以及每个进程消耗的系统资源. 右键单击还可以查看更多类别信息.
通过“页面右上角的三个小点---更多工具---任务管理器”打开相关面板,
Chrome任务管理器面板
Chrome的多进程体系结构的优缺点
好处
一个渲染过程的问题不会影响其他过程,并且更加安全. 不同进程的权限在系统级别受到限制.

缺点
由于不共享不同进程的内存,因此不同进程的内存通常需要包含相同的内容.
为了节省内存,Chrome限制了最大进程数. 最大进程数由设备的内存和CPU容量确定. 达到此限制后,新打开的标签页将共享同一网站的渲染过程.
已测试了Chrome的多进程体系结构的优缺点. 在Chrome中打开它,然后继续打开主页. 在Mac i5 8g上可以启动40多个渲染. 流程,之后新打开的标签页将合并到现有的渲染流程中.
Chrome将不同浏览器程序的功能视为服务,这些服务可以轻松划分为不同的进程或合并为一个进程. 以Broswer Process为例. 如果Chrome在强大的硬件上运行,则会将不同的服务拆分为不同的进程,从而使Chrome的整体运行更加稳定,但是如果Chrome在资源贫乏的设备上运行,则这些服务将合并并在同一进程中运行,这样可以节省内存,图表如下.
具有不同性能的硬件的不同处理分区
iframe渲染站点隔离
在上面的流程图中,我们还可以看到某些进程下存在子帧,这是站点隔离机制的作用的结果.
默认情况下,从Chrome 67开始启用站点隔离. 此机制允许在同一标签下的跨站点iframe可以在单独的过程中呈现,这更加安全.
iframe将使用不同的渲染过程“网站隔离”,这被视为里程碑功能. 它的成功实现是多年努力的结果. 站点隔离不仅仅是多个进程的堆栈. 这种机制会更改底部iframe之间的通信方式. Chrome的其他功能需要相应调整. 例如,devtools需要相应的支持,甚至还需要支持Ctrl +F. 有关网站隔离的更多信息,请参考developers.google.com
下面的链接.
介绍了浏览器的基本架构模式之后,让我们看看在常见的导航过程中浏览器会发生什么.
也许大多数人最常使用Chrome的情况是在地址栏中输入关键字以进行搜索或输入地址以导航至网站. 让我们看看浏览器如何看待这个过程.
我们知道,“浏览器”选项卡之外的工作主要由“浏览器进程”控制,该进程进一步由“浏览器进程”划分,并使用不同的线程进行处理:
{0: e: d: 0: a: 9: 8: 9: 2: d: 2: 0: b: 3: b: 2: 0: 4: 9: 8: 9: b: 8: 6: 9: 7: a: 5: c: 2: 2: 2: d)浏览器主进程中的不同线程
回到我们的问题,当我们在浏览器的地址栏中输入文本并单击Enter以获取页面内容时,浏览器可以分为以下步骤:
处理输入
UI线程需要确定用户输入的是URL还是查询;
2. 开始导航
当用户单击Enter键时,UI线程会通知网络线程获取网页内容,并控制选项卡上的微调器显示,表明该页面正在加载.
网络线程将执行DNS查询,然后为请求建立TLS连接
UI线程通知网络线程以加载相关信息
如果网络线程收到重定向请求标头(例如301),则网络线程将通知UI线程服务器请求重定向. 之后,将触发另一个URL请求.
3. 阅读回复
返回请求响应时,网络线程将根据Content-Type和MIME Type嗅探确定响应内容的格式.
判断响应内容的格式
如果响应内容的格式为HTML,则下一步是将这些数据传递给渲染器进程. 如果是zip文件或其他文件,则相关数据将传输到下载管理器.
此时也会触发“安全浏览”检查. 如果域名或请求的内容与已知的恶意站点匹配,则网络线程将显示警告页面. CORB检测还会触发以确保敏感数据不会传递到渲染过程.

{2: 9: 9: 6: 8: 4: 5: 3: 8: 6: 6: 9: 1: 0: 5: 5: 1: 1: c: 8: b: d: 7: 0: c: f: 7: 4: e: c: 0: b: d)
4. 寻找渲染过程
完成上述所有检查后,网络线程将确保浏览器可以导航到请求的网页,网络线程将通知UI线程数据已准备就绪,并且UI线程将找到渲染器进程. 呈现网页.
在收到网络线程返回的数据之后,UI线程会寻找相关的由于需要进行渲染,因此需要花费一些时间才能从网络请求中获得响应. 实际上,这里有一个加速方案. 当UI线程向网络线程发送URL请求时,浏览器实际上知道要导航到的站点. UI线程将预查找并并行开始渲染过程. 如果一切正常,则当网络线程接收到数据时,渲染过程已准备就绪,但是如果遇到重定向,则准备好的渲染过程可能不可用. 此时,您需要重新启动新的渲染过程.
5. 确认导航
进入上述过程后,数据和渲染过程即可使用. 浏览器进程将向渲染器进程发送IPC消息,以确认导航. 浏览器进程从渲染器进程接收到渲染确认消息后浏览器加载图片原理,导航过程结束,页面加载过程开始.
这时,地址栏将更新以显示新页面的网页信息. 历史记录选项卡将被更新. 您可以使用返回键返回到导航页面. 为了使关闭选项卡或窗口后易于还原,此信息将存储在硬盘上.
浏览器进程和Renderer进程通过IPC进行通信并请求Renderer进程呈现页面
6. 额外步骤
确认导航后,渲染器进程将使用相关资源渲染页面. 在下文中,我们将重点介绍渲染过程. 渲染器进程完成渲染后(结束渲染意味着页面中的所有页面,包括所有iframe均已触发onload),它将向浏览器进程发送IPC信号,并且UI线程将停止在选项卡中显示微调器. / p>
渲染器进程发送IPC消息以通知浏览器进程页面已加载
当然,以上过程仅呈现网页的第一帧. 之后,客户端仍然可以下载其他资源以呈现新视图.
我们在这里可以明确地说,所有JS代码实际上都是由渲染器进程控制的,因此浏览网页内容的大多数过程将不涉及其他进程. 但是也许您也听过了beforeunload事件. 此事件再次涉及浏览器进程与渲染器进程之间的交互. 当当前页面关闭时(关闭选项卡,刷新等),浏览器进程需要通知Renderer进程执行相关检查并执行相关检查. 要处理的事件.
浏览器进程将IPC消息发送到呈现过程,通知它正在离开当前网站
如果导航是由渲染器进程触发的(例如,当用户单击链接或JS执行`window.location =“#34;`)时,渲染器进程将首先检查是否存在“ beforeunload”. 事件处理程序,导航请求由渲染器进程执行传递到浏览器进程
如果您导航到新网站,将启用新的呈现过程来处理新页面的呈现,而旧过程将保留来处理诸如“卸载”之类的事件.
有关页面生命周期的更多信息,请参阅页面生命周期API.
浏览器进程向新的渲染过程发送IPC消息,以通知渲染一个新页面,同时通知旧的渲染过程卸载
除上述过程外,某些页面还具有服务工作者. 服务人员可让开发人员对本地缓存进行更多控制,并确定何时从网络获取信息. 如果将Service Worker设置为从本地缓存加载数据,则无需从Internet获取更多数据.
值得注意的是,服务工作者也是在呈现过程中运行的JS代码,因此对于具有服务工作者的页面,上述过程略有不同.
注册Service Worker后,其作用域将被保存. 进行导航时,网络线程将检查注册的Service Worker范围内的相关域名. 如果有对应的Service Worker,则UI线程将查找渲染器进程以处理相关代码. 服务工作者可以从缓存中加载数据,从而终止网络请求,也可以从Internet请求新数据.
服务人员将根据具体情况进行处理
有关服务工作者的更多信息,请参考服务工作者生命周期
如果服务工作者最终决定通过Internet获取数据,则浏览器进程与渲染器进程之间的交互实际上将延迟数据请求时间. 导航预加载是一种与Service Worker并行地加速资源加载的机制. 服务器可以通过请求标头识别这种类型的请求并进行相应处理.
有关更多详细信息,请参阅: 带有导航预载的加速服务工作者
渲染过程几乎负责选项卡中的所有内容. 呈现过程的核心目的是将HTML CSS JS转换为用户交互的网页. 渲染过程主要包括以下线程:
呈现过程中包含的线程主线程主线程工作线程布局线程复合线程栅格线程
我们将逐步介绍不同线程的职责. 在此之前,让我们看一下渲染过程.

构建DOM
当呈现过程收到导航确认并开始接受HTML数据时,主线程会将文本字符串解析为DOM.
将HTML呈现为DOM的方法由HTML标准定义.
2. 加载辅助资源
网页通常包含其他资源,例如图像,CSS,JS等. 这些资源需要从Internet或缓存中获取. 在构建DOM的过程中,主要过程可以一一请求. 为了加快预加载扫描仪的速度,它们将同时运行. 如果html中有诸如或之类的标签浏览器加载图片原理,则预加载扫描程序会将这些请求传递给浏览器进程The download相关资源中的网络线程.
3. 下载并执行JS
遇到`
中国可以在附近海