客户端容器-web浏览器以及跨端方案
- 浏览器架构
- 渲染进程
- Chrome运行原理
- 跨端容器
浏览器架构演进
-
单进程架构:所有模块运行在同一个进程里,包含网络、插件、JavaScript运行环境等
- 在早期的浏览器中,所有的功能都在一个进程中完成,包括用户界面、JavaScript执行、CSS渲染和网络请求等。单进程架构的优势是简单、易于实现,但缺点也很明显,如:不稳定(一个标签页崩溃可能导致整个浏览器崩溃)、不安全(攻击者可以利用漏洞来控制整个浏览器)以及性能瓶颈(多个标签页争抢资源,导致性能下降)。
-
多进程架构:主进程、网络进程、渲染进程、GPU进程、插件进程
- 为了解决单进程架构的问题,浏览器厂商开始将浏览器的功能拆分为多个进程。例如,谷歌推出的Chrome浏览器就采用了多进程架构。在这种架构下,浏览器将每个标签页(或每个渲染实例)分配给一个单独的进程,从而实现了进程间的隔离,防止单个网页崩溃影响到其他界面。多进程架构提高了浏览器的稳定性、安全性和性能,但同时也增加了内存消耗
- 每一个Tab运行在独立的沙盒里面
-
面向服务架构:将原来的UI、数据库、文件、设备、网络等,作为一个独立的基础服务
- 面向服务架构 => 多进程架构升级版本
- 随着Web平台的发展,浏览器需要处理越来越多的任务,这使得多进程架构变得复杂且难以维护。面向服务架构的出现旨在将浏览器的各个功能模块化,将它们作为独立的服务来运行和维护。在这种架构下,每个服务都可以独立地使用一个或多个进程,根据需求自动扩展或缩减资源。这样可以进一步提高浏览器的稳定性、安全性和性能,同时优化资源利用率
浏览器架构对比
浏览器架构 - 任务管理器
在多进程浏览器架构中,任务管理器是一个非常重要的组件。任务管理器负责监控、管理和分配浏览器的各个进程,确保整个浏览器系统的稳定性和性能。 任务管理器主要负责以下几方面的功能:
进程监控:任务管理器可以实时查看浏览器中的各个进程,包括标签页进程、插件进程和扩展进程等。它可以展示各个进程的资源使用情况,如内存占用、CPU使用率和网络活动等。
进程管理:任务管理器负责启动和关闭浏览器的进程。当用户打开一个新的标签页或启动一个插件时,任务管理器会创建相应的进程。当标签页被关闭或插件停止运行时,任务管理器会结束相应的进程,以释放系统资源。
资源分配:任务管理器根据各个进程的资源需求,动态地分配系统资源。例如,对于需要大量CPU资源的进程,任务管理器会分配更多的CPU时间片。同时,任务管理器还可以确保关键进程(如用户界面进程)始终获得足够的资源,从而保证整个浏览器的流畅运行。
进程隔离:为了提高浏览器的安全性,任务管理器会对各个进程进行隔离。这意味着一个进程无法直接访问另一个进程的内存空间。进程隔离可以防止潜在的安全漏洞影响到整个浏览器系统。
异常处理:任务管理器负责检测和处理进程中的异常情况。当某个进程发生崩溃或无响应时,任务管理器会尝试自动恢复该进程。如果无法恢复,任务管理器会提示用户关闭相应的标签页或插件,以防止整个浏览器崩溃。
通过任务管理器,浏览器可以有效地监控和管理其各个进程,确保整个系统的稳定性、性能和安全性。不同浏览器的任务管理器实现可能会有所差异,但它们的核心功能和目标都是类似的。在谷歌Chrome浏览器中,用户可以通过按下`Shift + Esc`快捷键或者在菜单中选择“更多工具” > “任务管理器”来打开任务管理器。
浏览器架构 - 多进程分工
进程名称 进程描述
浏览器(主进程) 主要负责页面展示逻辑,用户交互,子进程管理;包括地址栏、书签、前进、后退、收藏夹等
GPU进程 负责UI绘制,包含整个浏览器全部UI
网络进程 网络服务进程,负责网络资源加载
标签页(渲染进程) 控制tab内的所有内容,将HTML、CSS和JavaScript转换为用户可交互的网页
插件进程 控制网站运行的插件,比如flash、ModHeader等
其他进程 如上图所示:适用程序Storage/Network/Audio Service等
渲染进程
常见浏览器内核
渲染进程 - 多线程架构
在这里我们涉及到了(多)线程,前面涉及到了(多)进程。这里补充额外知识来说明两者:
进程和线程都是操作系统进行任务管理的基本单位,它们之间有一定的关联性,但也有明显的区别
- 进程:
进程是一个独立的程序执行实例,它包括程序的代码、数据以及运行时所需的系统资源(如文件描述符、内存空间等)。每个进程都有自己的独立地址空间,操作系统会为每个进程分配和管理资源。
进程的特点:
- 独立性:进程具有独立的地址空间,一个进程无法直接访问另一个进程的资源,除非通过进程间通信(IPC)机制。
- 隔离性:操作系统会为每个进程分配和管理资源,确保它们之间的隔离。这有助于提高系统的稳定性和安全性。
- 资源开销:创建和维护进程需要消耗一定的系统资源,如内存、CPU时间等。
应用场景:进程通常用于执行独立的、需要隔离的任务。例如,在多进程浏览器中,每个Tab标签页都运行在一个单独的进程中,以实现进程间的隔离和资源管理。
- 线程:
线程是进程内的一个执行单元,它共享进程的地址空间和资源,但拥有自己的执行堆栈和程序计数器。一个进程可以包含多个线程,它们可以并发地执行任务。
线程的特点:
- 轻量级:线程比进程更轻量级,创建和切换线程的开销较小。
- 共享资源:线程之间可以共享进程的地址空间和资源,这使得线程间的通信和数据共享变得更加简单高效。
- 上下文切换:线程之间的上下文切换成本较低,因为它们共享相同的地址空间。
应用场景:线程通常用于实现并发执行和任务分解。例如,在一个图形编辑器中,可以使用多个线程分别处理用户输入、图形渲染和文件保存等任务,从而提高程序的响应速度和执行效率。
总结:进程是一个独立的程序执行实例,具有独立的地址空间和资源;线程是进程内的一个执行单元,共享进程的地址空间和资源。进程通常用于执行独立的、需要隔离的任务,而线程则用于实现并发执行和任务分解
- 内部是多线程实现,主要负责页面渲染,脚本执行,事件处理,网络请求等
JS引擎 VS 渲染引擎
JS引擎和渲染引擎是浏览器中两个非常重要的组件。它们分别负责处理JavaScript代码和渲染网页内容
-
解析执行JS
- JS引擎:JS引擎负责解析和执行JavaScript代码。它会将JavaScript源代码解析成抽象语法树(AST),然后通过JIT编译器将AST编译成机器代码,最后执行机器代码。在这个过程中,JS引擎还会进行优化,提高代码的执行效率。常见的JS引擎包括V8(用于Chrome和Node.js)、SpiderMonkey(用于Firefox)和JavaScriptCore(用于Safari)。
- 渲染引擎:渲染引擎的主要任务是解析HTML和CSS,构建DOM树和渲染树,然后将渲染树转换为屏幕上的像素。在这个过程中,渲染引擎并不直接处理JavaScript代码。然而,当遇到需要执行的JavaScript代码时(例如,通过
<script>标签或事件处理程序),渲染引擎会将控制权交给JS引擎。一旦JS引擎执行完毕,渲染引擎会继续执行后续的渲染任务。
-
XML解析生成渲染树,显示在屏幕
- JS引擎:JS引擎主要处理JavaScript代码,不负责解析XML或生成渲染树。然而,JavaScript可以通过DOM API操作DOM树,从而间接地影响渲染树的生成和更新。
- 渲染引擎:渲染引擎负责解析HTML和XML文档,构建DOM树。然后,渲染引擎会解析CSS样式,并将样式信息附加到DOM树上,生成渲染树。接下来,渲染引擎会计算每个节点的布局信息(如位置和大小),并将渲染树转换为屏幕上的像素。这个过程被称为“绘制”或“渲染”。
-
桥接方式通信
- JS引擎和渲染引擎之间需要进行通信,以确保JavaScript代码的执行和网页内容的渲染能够协同工作。这种通信通常通过浏览器内部的API和事件机制实现。
- JS引擎:JS引擎提供了DOM API,使得JavaScript代码可以访问和操作DOM树。当JavaScript代码需要对DOM树进行操作时(如添加、删除或修改节点),JS引擎会通过浏览器内部的API通知渲染引擎进行相应的
渲染进程 - 多线程工作流程
-
网络线程负责加载网页资源
- 网络线程的主要任务是从服务器加载网页资源,如HTML、CSS、JavaScript、图片等。加载过程中,网络线程会将HTML和CSS交给渲染线程进行解析,并将JavaScript交给JS引擎进行解析和执行
-
JS引擎解析JS脚本并且执行
- JS引擎将接收到的JavaScript代码解析成抽象语法树(AST),然后通过JIT编译器将AST编译成机器代码,最后执行机器代码。在这个过程中,JS引擎还会进行优化,提高代码的执行效率
-
JS解析引擎空闲时,渲染线程立即工作
- 当JS引擎空闲时(即没有JavaScript代码需要执行),渲染线程开始工作。渲染线程负责解析HTML和CSS,构建DOM树和渲染树,计算布局信息,并将渲染树转换为屏幕上的像素。如果在此过程中遇到JavaScript代码(如
<script>标签或事件处理程序),渲染线程会暂停,将控制权交给JS引擎
- 当JS引擎空闲时(即没有JavaScript代码需要执行),渲染线程开始工作。渲染线程负责解析HTML和CSS,构建DOM树和渲染树,计算布局信息,并将渲染树转换为屏幕上的像素。如果在此过程中遇到JavaScript代码(如
-
用户交互、定时器操作等产生回调函数放入任务队列中
- 当用户与网页进行交互(如点击、滚动等),或者有定时器触发(如
setTimeout或setInterval)时,相应的回调函数会被放入任务队列中。任务队列是一个先进先出(FIFO)的数据结构,用于存储待处理的任务
- 当用户与网页进行交互(如点击、滚动等),或者有定时器触发(如
-
事件线程进行事件循环,将队列里的任务取出交给JS引擎执行
- 事件线程负责管理事件循环。事件循环的主要任务是检查任务队列,将队列中的任务按顺序取出,并交给JS引擎执行。JS引擎执行任务时,可能会对DOM树进行操作,从而触发渲染线程的更新。事件循环会持续进行,直到任务队列为空,或者浏览器关闭。
-
Chrome运行原理
Chrome运行原理 - 如何展示网页
- 浏览器地址输入URL后发生了什么(完整流程)
- 输入解析:浏览器首先解析输入的内容,判断它是一个有效的URL还是搜索查询。如果输入的内容被识别为搜索查询,浏览器将使用默认的搜索引擎进行搜索。
- DNS查询:如果输入的内容是一个有效的URL,浏览器将进行域名系统(DNS)查询以将域名解析为对应的IP地址。浏览器会首先检查本地DNS缓存,如果找不到对应的记录,它会向DNS服务器发送查询请求。
- 建立连接:浏览器与目标服务器建立一个TCP连接。这通常包括三次握手过程,以确保双方都准备好进行数据传输。
- 发送HTTP请求:TCP连接建立后,浏览器向服务器发送一个HTTP请求。请求通常包括请求方法(如GET或POST)、请求的资源路径、HTTP协议版本、请求头(包含诸如用户代理、接受的编码和语言等信息)以及可能的请求体(如POST请求所包含的表单数据)。
- 接收响应:服务器处理HTTP请求,并将响应数据发送回浏览器。响应通常包括HTTP状态码(如200表示成功,404表示未找到等)、响应头(包含诸如内容类型、内容长度等信息)以及响应体(通常是HTML文档)。
- 关闭或重用连接:一旦浏览器接收到完整的响应数据,它可以选择关闭TCP连接或将其保持在活动状态以用于后续请求。
- 解析HTML:浏览器解析HTML文档,构建DOM树。在解析过程中,浏览器可能遇到
<script>标签或其他需要立即执行的脚本,这时浏览器将暂停解析,执行脚本,然后继续解析。- 请求其他资源:HTML文档通常包含其他资源的引用,如CSS、JavaScript和图片等。浏览器将发送额外的HTTP请求来获取这些资源。这些请求可能与初始请求的服务器相同,也可能涉及其他服务器。
- 构建渲染树:浏览器解析CSS样式,并将其应用于DOM树,生成渲染树。渲染树包含了所有可见元素及其样式信息。
- 布局:浏览器计算渲染树中每个元素的位置和大小,生成布局信息。
- 绘制:浏览器根据渲染树和布局信息将元素绘制到屏幕上。这个过程称为绘制或渲染。浏览器会将各个层的元素绘制到位图中,然后将这些位图合成到屏幕上显示的最终图像。
- 交互:在完成页面绘制后,浏览器开始接收和处理用户的交互,如点击、滚动、输入等。这些交互可能会触发JavaScript事件处理程序,从而修改DOM或应用新的样式。这些修改可能会导致浏览器重新布局和绘制页面的部分或全部内容。
- 关闭或卸载:当用户导航到其他页面或关闭浏览器选项卡时,浏览器将触发相应的页面卸载事件,如
beforeunload和unload。这给开发者一个机会来执行清理操作,如保存用户数据或取消挂起的网络请求。一旦完成这些操作,浏览器将卸载页面并释放相关资源。总结:当您在浏览器地址栏输入URL后,浏览器会经历一系列的操作,从DNS查询和TCP连接建立,到HTTP请求、响应处理、HTML解析、资源加载、渲染树构建、布局、绘制以及用户交互等。这些操作共同构成了从输入URL到显示完整网页的整个过程
个人总结
了解到在浏览器里JS引擎和渲染引擎如何协同工作,如何从多个角度优化前端的性能体验。再以webview容器为扩展,认识一些常见的跨端方案。