浏览器的主要功能就是向服务器发出请求,在浏览器窗口中展示HTML文档、PDF、图片、视频等网络内容。这些网络资源的位置由用户使用 URI(统一资源标示符)来指定指定。
或许在大多数人眼中,浏览器是这样的:
大多数人眼中的浏览器
「一个展示前端,一个未知的中间层连接着网络世界」;甚至,网络世界也可以省略:一台显示器,一个神秘的幕后黑盒。
如果你是一个前端开发者,甚至每天浏览器陪伴你度过的时光比女朋友陪伴你的都要久,想想那每一个令人“不是那么期待”的早晨,每一个争分夺秒完成任务的黄昏,只有浏览器和编辑器一直是你忠实的伙伴。而「就连你一直离不开的VS Code编辑器,甚至也与浏览器有着莫大的渊源」。
屏幕前的朋友,你熟悉自己身边的那些人吗,熟悉那些与你朝夕相伴的朋友吗?也许熟悉,也许不,那么,你是否愿意花些时间来熟悉一下这个在大量时间里与你有着莫大交集的浏览器的内心世界呢?
今天,我们就来一探究竟,走进这个我们与网络连接最紧密的中间地带。全文行文结构大概如下:
目录结构
也许你知道,第一款浏览器 —— WorldWideWeb,诞生于1990年。但是现代浏览器的雏形却孕育于 1980s年代。
一位名叫蒂姆·伯纳斯-李的英国科学家在 1980 年代初期创建了一个名为 Inquire 的计算机程序,当时他在总部位于瑞士的欧洲核研究组织(CERN,以其法文字母表示)工作。该计划旨在「使在 CERN 工作的许多不同个人更容易共享信息」。
1990年,第一款浏览器问世于Tim Berners-Lee 在 CERN 工作期间。您可能想知道 Web 浏览器到底是什么,简而言之,它是一个计算机程序,其目的是显示和检索数据。使用分配给存储在网络服务器上的每个数据集(网页)的 URL,它可以做到这一点。所以这意味着「当您在浏览器中输入内容时,您实际上是在输入地址」,浏览器将使用该地址来获取您想要查看的信息。「浏览器的另一个关键功能是以易于理解的方式向您解释和呈现计算机代码」。
下图简单罗列了截止2020年浏览器的发展简史:
Timeline_of_the_Web_Browsers
早期比较有名、有意义的浏览器主要包括Erwise、ViolaWWW、Mosaic、Netscape Navigator:
The-Early-Browsers
1990年浏览器诞生之后的故事,想必您已经早有耳闻:
1995年8月9日,网景公开募股,最初的价格是14美元一股,但后来阴差阳错,改为28美元一股发行,当天收盘时,网景的股票成了75美元一股,网景成为了当时世界上市值最高的互联网公司,Netscape 的 IPO 也助长了日益增长的网络泡沫。
Market_Share_During_the_Browser_Wars
市场份额的快速下滑导致 Netscape 被出售给了 AOL,2003年7月,网景解散,就在解散的当天,Mozilla基金会成立,2004年基于Mozilla源码的Firefox首次登台,拉开了第二次浏览器大战的序幕。2008 年Netscape最终灭绝,「当年的浏览器帝国正式退出了历史的舞台」。
到 2003 年,微软的 Internet Explorer 控制了 92% 以上的市场,完全扭转了 1995 年的局面。然而,虽然微软在不到十年的时间里成功地完全接管了浏览器市场,但很快就会出现其他竞争,再次重塑网络浏览器的历史。
截止2021年7月初,浏览器市场份额如下所示。
浏览器使用趋势变化:
Web_Browser_Usage_Trends
浏览器市场份额:
Web_Browser_Market_Share
国内浏览器市场份额:
Web_Browser_Market_Share_CHN
如果你对以上浏览器市场份额数据有兴趣,可以通过以下链接进行查看:
国内浏览器市场份额
浏览器市场份额[1]
全球浏览器市场份额
全球浏览器市场份额[2]
w3counter[3]
三层计算机体系结构:底部是机器硬件,中间是操作系统,顶部是应用程序。
hw-os-app
当你在电脑或手机上启动应用时,是 「CPU 和 GPU 为应用供能」。通常情况下应用是通过操作系统提供的机制在 CPU 和 GPU 上运行。
中央处理器(Central Processing Unit),或简称为 CPU。CPU 可以看作是计算机的大脑。「一个 CPU 核心如图中的办公人员,可以逐一解决很多不同任务」。它可以在解决从数学到艺术一切任务的同时还知道如何响应客户要求。过去 CPU 大多是单芯片的。随着现代硬件发展,你经常会有不止一个内核,为你的手机和笔记本电脑提供更多的计算能力。
4 个 CPU 核心作为办公人员,坐在办公桌前处理各自的工作:
CPU
图形处理器(Graphics Processing Unit,简称为 GPU)是计算机的另一部件。与 CPU 不同,GPU 擅长同时处理跨内核的简单任务。顾名思义,「它最初是为解决图形而开发的」。这就是为什么在图形环境中“使用 GPU” 或 “GPU 支持”都与快速渲染和顺滑交互有关。近年来随着 GPU 加速计算的普及,仅靠 GPU 一己之力也使得越来越多的计算成为可能。
下图中,许多带特定扳手的 GPU 内核意味着它们只能处理有限任务。
GPU
进程可以被描述为是一个应用的执行程序。线程是位于进程内部并执行其进程程序的任意部分。
启动应用时会创建一个进程。程序也许会创建一个或多个线程来帮助它工作。操作系统为进程提供了一个可以使用的“一块”内存,所有应用程序状态都保存在该私有内存空间中。关闭应用程序时,相应的进程也会消失,操作系统会释放内存(下图中,边界框为进程,线程作为抽象鱼在进程中游动)。
memory
进程可以请求操作系统启动另一个进程来执行不同的任务。此时,内存中的不同部分会分给新进程。如果两个进程需要对话,他们可以通过**进程间通信(IPC)**来进行。许多应用都是这样设计的,所以如果一个工作进程失去响应,该进程就可以在不停止应用程序不同部分的其他进程运行的情况下重新启动。
workerprocess.gif
关于如何「构建 web 浏览器并不存在标准规范」,一个浏览器的构建方法可能与另一个迥然不同。不同浏览器的进程/线程架构一般由下图几部分:
browser-arch
而当下“浏览器世界的王者” Chrome 架构如下图所示,渲染进程下显示了多个层,表明 Chrome 为每个标签页运行多个渲染进程。
browser-arch-chrome
上图中,顶部是浏览器进程,它与处理应用其它模块任务的进程进行协调。对于渲染进程来说,创建了多个渲染进程并分配给了每个标签页。Chrome 在可能的情况下会给每个标签页分配一个进程。而现在它试图给每个站点分配一个进程,包括 iframe。
可以简单理解为不同进程对应浏览器 UI 的不同部分:
browserui
「Chrome 更多的是把自己抽象为一个操作系统,网页或扩展相当于一个个程序」,你甚至可以发现,Chrome 确实自带了一个任务管理器,在任务管理器面板会列出当前正在运行的进程以及它们当前的 CPU/内存使用量情况等信息。
一般你可以通过两种方法打开Chrome任务管理器:
task
前文中提到了 Chrome 使用多个渲染进程,那他有什么优势呢?
tabs.gif
由于进程有自己的私有内存空间,所以它们通常包含公共基础设施的拷贝(如Chrome V8引擎)。这意味着使用了更多的内存,如果它们是同一进程中的线程,就无法共享这些拷贝(同一个进程中的线程不共享堆栈,堆栈是保证线程独立运行所必须的)。为了节省内存,Chrome 对可启动的进程数量有所限制。具体限制数值依设备可提供的内存与 CPU 能力而定,但是「当 Chrome 运行时达到限制时,会开始在同一站点的不同标签页上运行同一进程」。
Chrome 正在经历架构变革,它转变为将浏览器程序的每一模块作为一个服务来运行,从而可以轻松实现进程的拆解或聚合。具体表现是,当 Chrome 运行在「强力硬件」上时,它会将每个服务分解到不同进程中,从而「提升稳定性」,但是如果 Chrome 运行在资源有限的设备上时,它会将服务聚合到一个进程中从而「节省了内存占用」。在这一架构变革实现前,类似的整合进程以减少内存使用的方法已经在 Android 类平台上使用。
servicfication.gif
Chrome 67 版本后,桌面版 Chrome 都默认开启了「站点隔离」,每个标签页的 iframe 都有一个单独的渲染进程。启用站点隔离是多年来工程人员努力的结果。站点隔离并不只是分配不同的渲染进程这么简单。它从根本上改变了 iframe 的通信方式。在一个页面上打开开发者工具,让 iframe 在不同的进程上运行,这意味着开发者工具必须在幕后工作,以使它看起来无缝。即使运行一个简单的 Ctrl + F 来查找页面中的一个单词,也意味着在不同的渲染器进程中进行搜索。你可以看到为什么「浏览器工程师把发布站点隔离功能作为一个重要里程碑」!
isolation
延伸阅读:Chrome 为什么多进程而不是多线程?[4]
如果您是一名前端工程师,那么,面试时你大概率会被问到过:从 URL 输入到页面展现到底发生了什么?,如果您对这一过程不太熟悉,建议看看下面两篇文章,在此不过多赘述:
浏览器的主要任务之一就是渲染展示页面,不同的浏览器内核,渲染过程也不完全相同,但大致流程都差不多,下面这张图片是火狐浏览器(Firefox,可以认为是Netscapede的涅槃重生)开发文档中的一张图片。
浏览器架构
上面这张图片大体揭示了浏览器的渲染展示流程,但是从浏览器的整体架构上来说,上面的图片展示的也许只是浏览器体系中的冰山一角。
通常意义下,浏览器架构是如下图这样的:
浏览器架构
包括地址栏、前进/后退按钮、书签菜单等。除了浏览器主窗口显示的您请求的页面外,其他显示的各个部分都属于用户界面。
用户界面和渲染引擎的桥梁,在用户界面和渲染引擎之间传送指令。浏览器引擎提供了开始加载URL资源 和一些其他高级操作方法,比如:重新加载、前进、后退动作,错误信息、加载进度等。
负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。
所谓浏览器内核就是指浏览器最重要或者说核心的部分"Rendering Engine",译为"渲染引擎"。负责对网页语法的解析,比如HTML、JavaScript,并渲染到网页上。所以浏览器内核也就是浏览器所采用的渲染引擎,渲染引擎决定这浏览器如何显示页面的内容和页面的格式信息。不同的浏览器内核对语法的解释也不相同,因此同一网页在不同内核的浏览器显示的效果也会有差异(浏览器兼容)。这也就是网页开发者在不需要同内核的浏览器中测试网页显示效果的原因。
RENDERING ENGINE
延伸阅读:曾红极一时的红芯浏览器,官网对其介绍是:拥有智能的认证引擎、渲染引擎、管控引擎,而且还有强大的“国密通讯协议”,支持统一管控、远程控制。2018年8月15日,红芯浏览器被爆出打开安装目录后出现大量和谷歌Chrome浏览器一致的同名文件,其安装程序的文件属性中也显示了原始文件名chrome.exe,红芯浏览器的官网已撤下了浏览器的下载链接。8月16日,红芯联合创始人高婧回应,红芯浏览器“包含‘Chrome’在里面”,但并非抄袭,而是“站在巨人的肩膀上去做创新”。
hongxin
言归正传,浏览器内核主要包括以下三个技术分支:排版渲染引擎、 JavaScript引擎,以及其他。
排版引擎:
浏览器的内核引擎,基本上是四分天下:
需要略作补充的是,我们经常还会听到Chromium、Webkit2、Blink这些引擎。
chromium 架构
图片来源:万字详文:深入理解浏览器原理[7]
各内核关系图:
KHTML
下面我们以WebKit为列,进行简单介绍,以便让你对渲染引擎有一个更多的理解。WebKit由多个重要模块组成,通过下图我们可以对WebKit有个整体的了解:
WebKit
WebKit就是一个「页面渲染以及逻辑处理引擎」,前端工程师把HTML、JavaScript、CSS这“三驾马车”作为输入,经过WebKit的处理,就输出成了我们能看到以及操作的Web页面。从上图我们可以看出来,WebKit由图中框住的四个部分组成。而其中最主要的就是WebCore和JSCore(或者是其它JS引擎)。除此之外,WebKit Embedding API是负责浏览器UI与WebKit进行交互的部分,而WebKit Ports则是让Webkit更加方便的移植到各个操作系统、平台上,提供的一些调用Native Library的接口,比如在渲染层面,在iOS系统中,Safari是交给CoreGraphics处理,而在Android系统中,Webkit则是交给Skia。
WebKit的渲染流程:
WebKit-Rendering
首先浏览器通过URL定位到了一堆由HTML、CSS、JS组成的资源文件,通过加载器把资源文件给WebCore。之后HTML Parser会把HTML解析成DOM树,CSS Parser会把CSS解析成CSSOM树。最后把这两棵树合并,生成最终需要的渲染树,再经过布局,与具体WebKit Ports的渲染接口,把渲染树渲染输出到屏幕上,成为了最终呈现在用户面前的Web页面。
用于网络调用,比如 HTTP 请求。其接口与平台无关,并为所有平台提供底层实现,负责网络通信和安全。
用于解析和执行 JavaScript 代码,执行结果将传递给渲染引擎来展示。
用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。
这是持久层,浏览器需要在硬盘上保存各种数据,例如 Cookie。新的 HTML 规范 (HTML5) 定义了“网络数据库”,这是一个完整而轻便的浏览器内数据库。
下面列出了部分浏览器的架构图,也许有些架构已经改变,有兴趣可以简单参考看看,除了IE之外,大体上各浏览器的整体架构都是类似的。
Mosaic架构:
Architecture_of_Mosaic
Firefox架构:
Architecture_of_Mozilla
Chrome架构:
Architecture_of_Chrome
Safari架构:
Architecture_of_Safari
IE架构:
IE架构
V8一词最早见于“V-8 engine”,即V8发动机,一般使用在中高端车辆上。8个气缸分成两组,每组4个,成V型排列。是高层次汽车运动中最常见的发动机结构,尤其在美国,IRL,ChampCar和NASCAR都要求使用V8发动机。
关于Chrome V8,笔者曾有一篇笔记做了比较详细的介绍,全文脉络如下,感兴趣可以参考阅读[8]。
Chrome-V8
V8是依托Chrome发展起来的,后面确不局限于浏览器内核。发展至今V8应用于很多场景,例如流行的nodejs,weex,快应用,早期的RN。V8曾经历过一次比较大的架构调整,主要变化在于“从字节码的放弃到真香”。
V8引擎诞生的使命就是要在速度和内存回收上进行革命。JavaScriptCore的架构是采用生成字节码的方式,然后执行字节码。Google觉得JavaScriptCore这套架构不行,生成字节码会浪费时间,不如直接生成机器码快。所以V8在前期的架构设计上是非常激进的,采用了直接编译成机器码的方式。后期的实践证明Google的这套架构速度是有改善,但是同时也造成了「内存消耗问题」。
V8-2010
早期的V8有Full-Codegen和Crankshaft两个编译器。V8 首先用 Full-Codegen把所有的代码都编译一次,生成对应的机器码。JS在执行的过程中,V8内置的Profiler筛选出热点函数并且记录参数的反馈类型,然后交给 Crankshaft 来进行优化。所以Full-Codegen本质上是生成的是未优化的机器码,而Crankshaft生成的是优化过的机器码。
随着网页的复杂化,V8也渐渐的暴露出了自己架构上的缺陷:
为了解决上述缺点,V8借鉴JavaScriptCore的架构,生成字节码。V8采用生成字节码的方式后,整体流程如下图:
V8-2017
现在的 V8 是一个非常复杂的项目,有超过 100 万行 C++代码。它由许多子模块构成,其中这 4 个模块是最重要的:
Parser[9]:负责将 JavaScript 源码转换为 Abstract Syntax Tree (AST)
确切的说,在“Parser”将 JavaScript 源码转换为 AST前,还有一个叫”Scanner“的过程,具体流程如下:
Scanner
Ignition[10]:interpreter,即解释器,负责将 AST 转换为 Bytecode,解释执行 Bytecode;同时收集 TurboFan 优化编译所需的信息,比如函数参数的类型;解释器执行时主要有四个模块,内存中的字节码、寄存器、栈、堆。Ignition的原始动机是减少移动设备上的内存消耗。在Ignition之前,V8的Full-codegen基线编译器生成的代码通常占据Chrome整体JavaScript堆的近三分之一。这为Web应用程序的实际数据留下了更少的空间。Ignition的字节码可以直接用TurboFan生成优化的机器代码,而不必像Crankshaft那样从源代码重新编译。Ignition的字节码在V8中提供了更清晰且更不容易出错的基线执行模型,简化了去优化机制,这是V8 自适应优化的关键特性。最后,由于生成字节码比生成Full-codegen的基线编译代码更快,因此激活Ignition通常会改善脚本启动时间,从而改善网页加载。
TurboFan[11]:compiler,即优化编译器,利用 Ignition 所收集的类型信息,将 Bytecode 转换为优化的汇编代码;TurboFan项目最初于2013年底启动,旨在解决Crankshaft的缺点。Crankshaft只能优化JavaScript语言的子集。例如,它不是设计用于使用结构化异常处理优化JavaScript代码,即由JavaScript的try,catch和finally关键字划分的代码块。很难在Crankshaft中添加对新语言功能的支持,因为这些功能几乎总是需要为九个支持的平台编写特定于体系结构的代码。
Orinoco[12]:garbage collector,垃圾回收模块,负责将程序不再需要的内存空间回收。
采用新的Ignition+TurboFan架构后,比Full-codegen+Crankshaft架构内存降低一半多,且70%左右的网页速度得到了提升。
在运行 C、C++以及 Java 等程序之前,需要进行编译,不能直接执行源码;但对于 JavaScript 来说,我们可以直接执行源码(比如:node test.js
),它是在运行的时候先编译再执行,这种方式被称为「即时编译(Just-in-time compilation)」,简称为 JIT。因此,V8 也属于 「JIT 编译器」。
V8未诞生之前,早期主流的JavaScript引擎是JavaScriptCore引擎。JavaScriptCore(以下简称JSCore)主要服务于Webkit浏览器内核,他们都是由苹果公司开发并开源出来。JSCore是WebKit默认内嵌的JS引擎,之所以说是默认内嵌,是因为很多基于WebKit分支开发的浏览器引擎都开发了自家的JS引擎,其中最出名的就是前文提到的Chrome的V8。这些「JS引擎的使命都是解释执行JS脚本」。而在渲染流程上,JS和DOM树之间存在着互相关联,这是因为浏览器中的JS脚本最主要的功能就是操作DOM树,并与之交互。我们可以通过下图看下它的工作流程:
JavaScriptCore
JavaScriptCore主要模块:「Lexer 词法分析器,将脚本源码分解成一系列的Token;Parser 语法分析器,处理Token并生成相应的语法树;LLInt 低级解释器,执行Parser生成的二进制代码;Baseline JIT 基线JIT(just in time 实时编译);DFG 低延迟优化的JIT;FTL 高通量优化的JIT」。
可以看到,相比静态编译语言生成语法树之后,还需要进行链接,装载生成可执行文件等操作,解释型语言在流程上要简化很多。这张流程图右边画框的部分就是JSCore的组成部分:Lexer(词法分析)、Parser(语法分析)、LLInt以及JIT(解释执行)的部分(之所以JIT的部分是用橙色标注,是因为并不是所有的JSCore中都有JIT部分)。
PS:严格的讲,语言本身并不存在编译型或者是解释型,因为语言只是一些抽象的定义与约束,并不要求具体的实现,执行方式。这里讲JS是一门“解释型语言”只是JS一般是被JS引擎动态解释执行,而并不是语言本身的属性。
如果对JavaScriptCore有更多兴趣,关于JavaScriptCore的更多细节,建议延伸阅读以下几篇博文:
这一小结,还是以Chrome V8为例,简单阐述浏览器与JavaScript的关系。
在 「V8 出现之前,所有的 JavaScript 虚拟机所采用的都是解释执行的方式,这是 JavaScript 执行速度过慢的一个主要原因」。而 V8 率先引入了「即时编译(JIT)**的**双轮驱动」的设计(混合使用编译器和解释器的技术),这是一种权衡策略,「混合编译执行和解释执行这两种手段」,给 JavaScript 的执行速度带来了极大的提升。V8 出现之后,各大厂商也都在自己的 JavaScript 虚拟机中引入了 JIT 机制,所以目前市面上 JavaScript 虚拟机都有着类似的架构。另外,「V8 也是早于其他虚拟机引入了惰性编译、内联缓存、隐藏类等机制,进一步优化了 JavaScript 代码的编译执行效率」。
V8 执行一段 JavaScript 的流程如下图所示:
V8执行一段JavaScript流程图
结合上文介绍的Chrome V8 架构,聚焦到JavaScript上,浏览器拿到JavaScript源码,Parser,Ignition 以及 TurboFan 可以将 JS 源码编译为汇编代码,其流程图如下:
V8流程
简单地说,Parser 将 JS 源码转换为 AST,然后 Ignition 将 AST 转换为 Bytecode,最后 TurboFan 将 Bytecode 转换为经过优化的 Machine Code(实际上是汇编代码)。
图片中的红色虚线是逆向的,也就是说 Optimized Machine Code 会被还原为 Bytecode,这个过程叫做 「Deoptimization」。这是因为 Ignition 收集的信息可能是错误的,比如 add 函数的参数之前是整数,后来又变成了字符串。生成的 Optimized Machine Code 已经假定 add 函数的参数是整数,那当然是错误的,于是需要进行 Deoptimization。
function add(x, y) {
return x + y;
}
add(1, 2);
add('1', '2');
「V8 本质上是一个虚拟机」,因为计算机只能识别二进制指令,所以要让计算机执行一段高级语言通常有两种手段:
简单总结如下,「V8 执行一段 JavaScript 代码所经历的主要流程」包括:
关于异步编程和消息队列,UI 线程提供一个消息队列,并将待执行的事件添加到消息队列中,然后 UI 线程会不断循环地从消息队列中取出事件、执行事件,通用 UI 线程宏观架构如下图所示:
v8-ui
「WebView 是一种嵌入式浏览器,原生应用可以用它来展示网络内容」。WebView 只是一个「可视化的」组件/控件/微件等。这样我们可以用它来作为我们原生 app 的视觉部分。当你使用原生应用时,WebView 可能只是被隐藏在普通的原生 UI 元素中,你甚至用不到注意到它。
如果你把浏览器想象成两部分,一部分是 UI(地址栏,导航栏按钮等),其它部分是把标记跟代码转换成我们可见和可交互视图的引擎。「WebView 就是浏览器引擎部分」,你可以像插入 iframe 一样将 Webview 插入到你的原生应用中,并且编程化的告诉它将会加载什么网页内容。
运行在你的 WebView 中的 JavaScript 有能力调用原生的系统 API。这意味着你不必受到 Web 代码通常必须遵守的传统浏览器安全沙箱的限制。下图解释了使用这种技术后的架构差异:
webview and webapp
默认情况下,在 WebView 或 Web 浏览器中运行的任何 Web 代码都与应用的其余部分保持隔离。这样做是出于安全原因,主要是为降低恶意的 JavaScript 代码对系统造成的伤害。对于任意 Web 内容,这种安全级别很有意义,因为你永远不能完全信任加载的 Web 内容。但 WebView 的情况并非如此,对于 WebView 方案,开发人员通常可以完全控制加载的内容。恶意代码进入并在设备上造成混乱的可能性非常低。
「这就是为什么对于 WebView,开发人员可以使用各种受支持的方式来覆盖默认的安全行为,并让 Web 代码和原生应用代码相互通信。这种沟通通常称为 bridge」。你可以在上文的图片中看到 bridge 可视化为 Native Bridge 和 JavaScript Bridge 的一部分。
WebView 非常好,虽然它看起来像是完全特殊和独特的,但请记住,它们只不过是一个在应用中设置好位置和大小的、没有任何花哨 UI 的浏览器,这就是它的精髓。大多数情况下,除非您调用原生 API,否则您不必在 WebView 中专门测试您的 Web 应用程序。此外,您在 WebView 中看到的内容与您在浏览器中看到的内容相同,尤其是使用同一渲染引擎时:
WebView 的应用:
如果你对 WebView 感兴趣,可通过以下几篇文章继续了解:
「无头浏览器」是一种未配置图形用户界面 (GUI) 的 Web 浏览器,通常通过命令行或网络通信来执行。它主要由软件测试工程师使用,没有 GUI 的浏览器执行速度更快,因为它们不必绘制视觉内容。无头浏览器的最大好处之一是它们能够在没有 GUI 支持的服务器上运行。
Headless 浏览器对于测试网页特别有用,因为它们能够像浏览器一样呈现和理解超文本标记语言,包括页面布局、颜色、字体选择以及JavaScript和AJAX的执行等样式元素,这些元素在使用其他测试方法时通常是不可用的。
Headless_architecture
Headless 浏览器有两个主要可交付成果:
Architecture_of_Puppeteer
Puppeteer 是一个 Node 库,他提供了一组用来操纵 Chrome 的 API, 通俗来说就是一个 headless chrome 浏览器 (当然你也可以配置成有 UI 的,默认是没有的)。既然是浏览器,那么我们手工可以在浏览器上做的事情 Puppeteer 都能胜任, 另外,Puppeteer 翻译成中文是”木偶”意思,所以听名字就知道,操纵起来很方便,你可以很方便的操纵她去实现:
1) 生成网页截图或者 PDF 2) 高级爬虫,可以爬取大量异步渲染内容的网页 3) 实现 UI 自动化测试,模拟键盘输入、表单自动提交、点击、登录网页等 4) 捕获站点的时间线,以便追踪你的网站,帮助分析网站性能问题 5) 模拟不同的设备 6) ...
Puppeteer 跟 webdriver 以及 PhantomJS 最大的 的不同就是它是站在用户浏览的角度,而 webdriver 和 PhantomJS 最初设计就是用来做自动化测试的,所以它是站在机器浏览的角度来设计的,所以它们 使用的是不同的设计哲学。
Electron(原名为Atom Shell)是 GitHub 开发的一个开源框架。它通过使用 Node.js(作为后端)和Chromium 的渲染引擎(作为前端)完成跨平台的桌面 GUI 应用程序的开发。现已被多个开源 Web 应用程序用于前端与后端的开发,著名项目包括 GitHub 的 Atom 和微软的 Visual Studio Code。
Electron
Electron Architecture 由多个 Render Process 和一个 Main 进程组成。Main Process 启动Render Process,它们之间的通信是通过IPC [Inter Process Communication],如下图所示。
Electron_Architecture
我们常用的IDE VSCode 就是基于 Electron (原来叫 Atom Shell) 进行开发的。如下图所示,(点击 VSCode 帮助【Help】 下的 切换开发人员工具即可打开以下面板)。
VSCode
VS Code 的其他的主要组件有:
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/MXqanvWl1HuoFmRI5mJ8OA
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。