客户端容器
思维导图:
一.浏览器架构
浏览器架构包括四个主要部分:用户界面(UI)、浏览器引擎、渲染引擎以及网络层。下面分别介绍这四个部分:
用户界面(UI):用户界面是用户看到和交互的部分,包括地址栏、前进和后退按钮、书签栏等。用户界面接收用户输入,然后将这些输入传输到浏览器引擎进行处理。大多数浏览器提供了自定义用户界面的能力,例如通过浏览器扩展和主题。 浏览器引擎:浏览器引擎提供了一个API来供UI与渲染引擎进行交互。浏览器引擎主要负责处理用户输入以及渲染请求。当用户在UI上输入URL时,浏览器引擎会向网络层发出请求,以获取指定URL的内容。 渲染引擎:渲染引擎负责将浏览器引擎请求到的内容渲染成用户界面。渲染引擎能够处理HTML、CSS、JavaScript等内容,将它们转换为可供浏览器显示的内容,例如DOM文档、渲染树以及最终的像素画面。渲染引擎的很多功能都由各种JavaScript库和框架提供支持。 网络层:网络层负责在浏览器引擎请求内容时和服务器进行通信。网络层使用各种协议与服务器进行通信,包括HTTP、TCP、UDP等。网络层还负责处理Cookie、SSL/TLS以及其它相关的功能。
以上四个部分一起协同工作,从而构成了浏览器的整体架构。不同的浏览器也可能在这四个部分元素以及性能、安全等方面进行不同的优化和改进。
浏览器架构演变
浏览器架构在过去几十年不断演变和改进,主要体现在以下几个方面:
单进程架构:早期的浏览器都采用单进程架构,即浏览器的UI、浏览器引擎、渲染引擎和网络层等全部运行在一个进程中。这种架构简单,但有一个很大的问题就是若其中一个组件崩溃,整个浏览器都会崩溃。 多进程架构:随着计算机硬件性能的提高和多线程技术的成熟,浏览器逐渐采用多进程架构,将UI和渲染引擎分离到单独的进程中。同时,浏览器引擎和网络层也运行在单独的进程中。这种架构能够提高浏览器的稳定性和安全性,但需要考虑进程间通信的问题。 进一步拆分:近年来,浏览器架构进一步拆分,如Google Chrome引入了代理进程(Browser Process)、渲染进程(Renderer Process)、GPU进程、网络进程等组件,并运用通信接口(IPC)来实现进程之间的通信。 WebAssembly:除了进程架构的调整以外,最新的WebAssembly技术则改变了浏览器处理代码的方式。WebAssembly允许开发人员在浏览器环境下运行低层次(类似于汇编)的代码,以取代JavaScript。它的优势在于,由于其精简的代码结构和直接的机器语义,能够在处理特定类型的任务时提供比JavaScript更高的性能。
随着技术的不断更新,浏览器架构也将不断地演变和改进,以更好地满足Web应用程序的需求。
浏览器架构对比
思考:为什么会有单进程架构?面向服务架构是否会替代多进程架构?
单进程架构的主要优势在于简单,易于设计和实现,因此它最初被广泛采用。但这种架构存在严重的缺陷,即若一个组件崩溃,整个浏览器都会崩溃,且单进程浏览器无法实现并行处理多任务,因此无法处理大量的数据和复杂的应用程序。 进程和线程带来了更高效和可靠的浏览器架构。多进程架构通过将一些浏览器组件分离到单独的进程中,如渲染进程和插件进程等,实现了更好的内存隔离和更快的响应速度。而在多进程架构中,每个进程互相独立,承担各自的任务,故单个进程的崩溃并不会影响其他进程。 面向服务架构是一种分布式系统设计方法,它将复杂的应用程序拆分成小而自治的单元,这些单元通常可以部署在不同的计算机上。因此,它可以更好地实现大规模并行处理,同时也具有更好的可扩展性、可靠性和安全性。 尽管面向服务架构确实可以带来许多优势,但它并不是多进程架构的替代品,因为两者的设计目的和实现方式都不同。尤其是从浏览器的角度来看,面向服务架构需要浏览器具备更多的分布式系统管理功能,例如服务注册、发现、部署和监测等。而多进程架构更适用于处理浏览器的核心功能,利用多进程进行内存隔离和各进程之间的通信,实现更好的安全和性能。因此,在未来可预见的一段时间内,多进程架构应该仍然是浏览器架构中的重要一环。
二.渲染进程
渲染进程(Rendering Process)是浏览器中负责显示网页内容的进程。每个标签页都有一个独立的渲染进程,负责渲染该标签页中的所有网页内容。 渲染进程主要负责以下任务:
根据 HTML、CSS、JavaScript 等网页资源,生成 DOM 树、CSSOM 树和渲染树。 布局渲染树,计算元素的位置和尺寸。 将渲染树转化为绘制指令,将页面绘制在浏览器窗口上。 处理用户事件,例如鼠标点击、键盘输入等,响应用户的操作。 和其他进程进行通信,例如网络进程、GPU 进程等。
渲染进程的架构通常是多进程的,即一个浏览器窗口会有多个渲染进程。主要包括以下类型的进程:
浏览器进程:管理所有渲染进程并提供浏览器的其他功能,例如地址栏、书签、历史记录等。 GPU 进程:负责在 GPU 上执行图形绘制操作,为提高性能而使用独立进程。 网络进程:负责处理所有网络请求和响应,包括 HTTP、WebSocket、FTP 等。 插件进程:负责对插件(例如 Flash、Java)的运行和管理,现已经逐渐淘汰。
渲染进程的设计目标是保证网页内容的安全性和隔离性,防止恶意网站攻击用户的电脑。例如,每个渲染进程都有自己的沙盒环境,网页脚本无法访问其他进程的资源和数据。同时,渲染进程可以随时终止和重启,以避免出现致命错误导致整个浏览器崩溃的情况。
常见浏览器内核
多线程架构
多线程架构指的是在一个系统或应用中使用多个线程来完成不同的任务。在多线程架构中,每个线程都可以独立运行,同时可以与其他线程共享内存和其他系统资源。这可以大大提高系统的并发性和响应能力。 在多线程架构中,通常存在一个主线程(也称为主进程),它负责协调所有子线程的执行,并在需要时进行资源分配和管理。每个子线程都有自己的执行上下文(包括栈、寄存器和计数器等),它们可以并行执行不同的任务,而不会互相干扰。 多线程架构可以应用于许多不同的领域,包括软件开发、服务器端编程、数据处理等等。在软件开发中,多线程架构可以用于加速应用程序的执行时间,提高响应速度和用户体验。在服务器端编程中,多线程架构可以用于处理并发请求,提高系统的性能和可扩展性。在数据处理中,多线程架构可以用于并行处理大量数据,提高处理效率和减少等待时间。 虽然多线程架构可以带来许多好处,但也存在一些挑战和风险。例如,多线程编程可能会导致线程间的竞争和死锁等问题,需要进行详细的设计和测试。另外,多线程架构也会增加系统的复杂性和管理难度,需要仔细权衡其利弊。
工作流程:
三.Chrome运行原理
如何展示网页
输入处理
1.用户Url框输入内容的后,UI线程会判断输入的是一个URL地址呢,还是一个query查询条件
2.如果是URL,直接请求站点资源
3.如果是query ,将输入发送给搜索引擎
开始导航
1.当用户按下回车,UI线程通知网络线程发起一个网络请求,来获取站点内容
2.请求过程中,tab处于loading状态
读取响应
1 ﹒网络线程接收到HTTP响应后,先检查响应头的媒体类型(MIME Type) 2.如果响应主体是一个HTML文件.浏览器将内容交给渲染进程处理 3.如果拿到的是其他类型文件,比如Zip.exe等,则交给下载管理器处理
寻找渲染进程
1 .网络线程做完所有检查后,会告知主进程数据已准备完毕,主进程确认后为这个站点寻找一个渲染进程
2.主进程通过IPC消息告知渲染进程去处理本次导航
3.渲染进程开始接收数据并告知主进程自己已开始处理,导航结束,进入文档加载阶段
资源加载
1﹒收到主进程的消息后,开始加载HTML文档
2.除此之外,还需要加载子资源,比如一些图片, cSS样式文件以及JavaScript脚本
构建渲染树
1 ﹒构建DOM树,将HTML文本转化成浏览器能够理解的结构
2.构建cSSOM树,浏览器同样不认识css,需要将CSS代码转化为可理解的CSSOM
3.构建渲染树,渲染树是DOM树和CSSOM树的结合
页面布局
1 .根据渲染树计算每个节点的位置和大小
2.在浏览器页面区域绘制元素边框
3.遍历渲染树,将元素以盒模型的形式写入文档流
页面绘制
1.构建图层:为特定的节点生成专用图层
2.绘制图层:一个图层分成很多绘制指令,然后将这些指令按顺序组成一个绘制列表,交给合成线程
3.合成线程接收指令生成图块
4.栅格线程将图块进行栅格化
5.展示在屏幕上
首屏优化
首屏优化是指在网页加载过程中,先加载用户所能看到的内容,即首屏内容。首屏内容是指用户打开网页时,可见区域内能够展示的内容。通过首屏优化,可以提高用户体验、减少用户等待时间,增加页面的转化率。 以下是几种常见的首屏优化方法: 1.压缩资源文件大小:压缩CSS、JS、图片等文件大小可以减少首屏加载时间,提高网页速度。使用图片压缩工具可以减小图片大小,使用JS压缩工具可以移除多余的空格、注释等信息,以此来减小文件大小。 2.使用缓存:使用浏览器缓存和CDN缓存可以减少资源请求,从而提高网页加载速度。一些不经常更改的静态资源可以设置长时间的缓存,减少服务器请求,提高缓存效率。 3.异步加载内容:将不必要已经的内容进行异步加载,比如相关文章推荐、广告、评论等内容。这样可以先加载首屏必要内容,让用户快速进入页面,异步加载的内容可以在页面渲染完成后再加载。 4.减少HTTP请求:减少各种不必要的HTTP请求可以提高页面加载速度。可以将CSS和JS文件合并,将多个图片合并成一张雪碧图。 5.使用响应式布局:使用响应式布局可以适配不同大小的设备,提高移动端用户体验。同时可以减少不必要的HTTP请求。 6.延迟加载图片:将页面中不重要或在用户当前屏幕之外的图片设置为延迟加载,等到用户滑动页面时再加载对应的图片。这样可以在保证首屏加载速度的情况下,提高页面加载的整体速度。 综上所述,以上是几种常见的首屏优化方法,通过这些方法能够帮助网页实现更快的加载速度,提高用户体验,增加页面转化率。
渲染优化
渲染优化是指在计算机图形渲染中通过一系列技术手段,提高渲染速度和质量,减少硬件要求和消耗。渲染是指将三维模型转化为二维图像,通常在计算机图形学、电影制作、游戏设计等领域常常出现。 以下是常见的渲染优化方法:
减少多边形数量:多边形是构建三维模型的基本单元,因此减少多边形数量可以提高渲染速度。这可以通过使用简化算法来达到,如网格简化和边缘抽样等技术。 使用级别细节技术:这通常用于减少远处对象的细节级别,从而进一步减少多边形数量。当远离对象时,渲染器可以用较低分辨率代替高分辨率的对象,从而提高渲染速度。 使用视锥体裁剪:通过将场景分割成可见和不可见的区域,从而减少需要渲染的对象数量。视锥体通常用于裁剪不可见区域,而不可见区域通常包括摄像机在视线范围之外的物体。 使用LOD:LOD(Level of Detail)是通过在渲染中根据物体与相机距离的远近来调整对象的细节级别。这样可以在不同距离时使用不同的细节级别,从而提高渲染速度。 使用合批:合批是将多个小的渲染任务合并成一个大的渲染任务来优化渲染速度。这样可以避免多次切换渲染状态和使用相同纹理的对象重复渲染,从而减少了CPU和GPU之间的通信。 GPU优化:GPU是计算机中最重要的图形处理器,因此优化GPU的使用可以显著提高渲染速度。这包括使用GPU引擎处理渲染任务以及使用各种优化技术减少GPU计算的负载。
总之,渲染优化旨在提高渲染速度和质量,减少硬件要求和消耗。它是一个不断进化的领域,需要不断更新和改进来适应不断发展的渲染技术。
JS优化
JavaScript (JS) 是一门非常重要的前端开发语言,但是它的性能可能会受到很多限制。下面是一些如何优化 JavaScript 代码的一些方法:
避免使用全局变量:全局变量会被多个函数共享,而且在函数调用时每次都要进行作用域查找,所以可能会影响性能。可以使用 IIFE、模块化或者闭包等方法来限制变量的范围。 缓存重复计算结果:在循环中,尤其是嵌套循环中,可能会有重复计算的情况,例如获取 DOM 元素的位置信息等。可以将这些值缓存起来,避免重复计算。 选择正确的数据类型:JavaScript 支持多种数据类型,例如字符串、数字、布尔值等。选择正确的数据类型可以避免类型转换的开销,提高性能。 使用高阶函数:高阶函数可以简化代码逻辑,而且可以利用 JavaScript 函数式编程的特性。例如可以使用 map、reduce、filter 等函数来对数组操作,避免手动循环。 避免不必要的 DOM 操作:DOM 操作是比较消耗性能的,因为每次操作都要从内存中获取并更新元素信息。可以将 DOM 操作尽可能地缩减到最少,例如使用文档片段来减少多次插入的消耗。 避免不必要的网络请求和数据传输:在前端开发中,网络请求和数据传输往往是性能瓶颈之一。可以使用缓存技术、利用浏览器缓存等方式来减少请求次数和数据传输量。 使用 Web Workers:Web Workers 是一种多线程的解决方案,可以将一些耗时的操作放在后台线程中运行,避免阻塞 UI 线程。例如可以使用 Web Workers 来进行图片处理、计算等操作。 开启 JavaScript 引擎的优化:JavaScript 引擎有一些优化技术,例如 Just-In-Time 编译、预编译等,可以提高代码的执行效率。可以使用一些工具来检测 JavaScript 代码的性能瓶颈,例如 Chrome DevTools、Firefox Developer Tools 等。
以上是优化 JavaScript 代码的一些方法,但是优化要基于具体场景和需求,需要根据具体业务需求来决定何时采用何种优化方案。
四.跨端容器
为什么要跨端
跨端指的是在不同的终端设备上(如PC、手机、平板等)使用同一应用程序或服务。 跨端的出现是因为随着移动互联网的普及,用户使用互联网的设备越来越多样化。为了让用户在不同的设备上都能顺畅地使用应用程序或服务,跨端已经成为了现在应用程序和服务的基本需求。 具体来说,为什么要跨端呢?
用户需求多样化:随着移动设备的普及,用户需要在手机、PC或平板等不同的终端设备上使用同一应用程序或服务。 更好的用户体验:跨端可以让用户无缝地在不同设备上使用应用程序或服务,提高用户的使用体验。 增强应用程序或服务的竞争优势:现在应用程序和服务领域瞬息万变,只有跨端才能更好地满足用户需求,提高应用程序或服务的竞争力。 降低产品研发成本:跨端可以使应用程序或服务可以在不同终端设备上重用代码,降低产品研发成本。
综上所述,跨端已经成为了应用程序和服务的基本需求,它可以提高用户体验,增强竞争优势,降低产品研发成本等好处,所以应用程序和服务提供商应该认真对待跨端的问题。
跨端方案
跨端方案是指通过一种技术或框架,使开发人员能够开发多个平台上的应用程序,例如Web应用程序、移动应用程序和桌面应用程序。以下是几种常见的跨端方案:
Webview:Webview是应用程序中显示网站或 Web 应用程序的小型浏览器窗口。Webview通常用于移动应用程序,但它们也可用于桌面应用程序或其他较大的 Web 应用程序。当开发人员需要在其应用中显示第三方内容(例如广告或社交媒体源)时,通常会使用它们。Webview可以使用各种编程语言和框架构建,包括Android,iOS,React Native和Electron。在某些情况下,与成熟的Web浏览器相比,Web视图在功能方面可能受到限制,但它们通常可以处理基本的HTML,CSS和JavaScript。
React Native:React Native是一种基于JavaScript的开发框架,它可以让开发人员使用React的语法来构建原生iOS和Android应用程序。由于React Native具有独特的开发方式,因此可以快速构建高性能且功能丰富的移动应用程序。 Flutter:Flutter是一种使用Dart编程语言的开源UI框架,它可用于构建高性能、美观、快速的移动应用程序。Flutter的热重载功能使得开发人员可以在应用程序运行时快速修改代码,并即时看到应用程序的更新。 Electron:Electron是一个基于Web技术的跨平台框架,用于构建桌面应用程序。使用HTML、CSS和JavaScript等Web技术,开发人员可以创建具有原生应用程序功能的桌面应用程序。 Xamarin:Xamarin是一种用于构建iOS、Android和Windows移动应用程序的跨平台开发框架,它使用C#编程语言和.NET框架为开发人员提供了一个统一的代码库。 Apache Cordova:Apache Cordova是一个开源平台,用于构建跨平台移动应用程序。Cordova允许开发人员使用HTML、CSS和JavaScript等Web技术来构建移动应用程序,并将其打包为原生应用程序。
这些跨端方案都有自己的优点和适用场景,开发人员可以根据项目需求和技术经验选择适合自己的跨端方案。
webview
webview是某些软件开发平台和框架中可用的视图,它允许开发人员在其应用程序中嵌入和显示 Web 内容。从本质上讲,Web 视图是应用程序中显示网站或 Web 应用程序的小型浏览器窗口。
webview通常用于移动应用程序,但它们也可用于桌面应用程序或其他较大的 Web 应用程序。当开发人员需要在其应用中显示第三方内容(例如广告或社交媒体源)时,通常会使用它们。
Webview可以使用各种编程语言和框架构建,包括Android,iOS,React Native和Electron。在某些情况下,与成熟的Web浏览器相比,Web视图在功能方面可能受到限制,但它们通常可以处理基本的HTML,CSS和JavaScript。
使用 webview时的一个重要注意事项是安全性。由于 Web 视图本质上是嵌入在应用程序中的独立浏览器会话,因此它们可能容易受到某些类型的攻击,例如跨站点脚本 (XSS)。开发人员需要采取措施确保 Web 视图的安全,并保护应用和用户的数据。
webview原生能力
在移动端开发中,WebView 是一个比较常用的组件,它可以在应用内嵌入浏览器窗口,用于展示网页、H5 应用等。WebView 提供了许多接口,其中一个比较关键的功能是它可以与原生代码交互,即通过 JavaScript Bridge 的方式调用原生能力来实现一些功能。 Webview 可以直接调用原生能力,一般的做法是在 WebView 初始化时,将一个 Native 对象注入到 WebView 的 JavaScript 上下文中,这个对象包含了一些可以在 WebView 中调用的方法。 以下是一个简单的示例,演示了如何在 WebView 中注册一个 Native 对象,并在 WebView 中通过这个对象调用原生代码: // 注册一个 Native 对象,用于在 WebView 中调用原生代码 class NativeObject { // 声明一个和 JavaScript 交互的接口,可以在 WebView 中通过 window.native.showToast() 调用这个方法 @JavascriptInterface public void showToast(String message) { Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show(); } }
WebView webView = findViewById(R.id.web_view);
// 注入 Native 对象到 JavaScript 上下文中 webView.addJavascriptInterface(new NativeObject(), "native");
在上面的代码中,我们定义了一个 NativeObject 类,并使用 WebView 的 addJavascriptInterface() 方法将这个对象注入到 WebView 的 JavaScript 上下文中,并起名为 "native" 。然后,我们可以在 WebView 中通过 window.native 调用这个对象的方法。 例如,可以在 WebView 的 HTML 中添加以下代码: Show Toast
当用户点击 "Show Toast" 按钮时,WebView 就会调用 NativeObject.showToast() 方法,这个方法又会调用原生代码来显示一个 Toast。 需要注意的是,为了确保安全性,我们应该只将必要的原生能力暴露给 JavaScript,避免将敏感数据和功能暴露给 WebView 中的 JavaScript。同时,在实际开发中,我们也需要考虑 WebView 的性能和安全等方面的问题。