共计 7503 个字符,预计需要花费 19 分钟才能阅读完成。
对于浏览器的那些事儿
七拼八凑了一些浏览器内容(^-^)
支流浏览器比照与倒退
- 举荐一个短视频介绍
浏览器 / 参数 | 厂商 | 内核 | JS 引擎 | 其余 |
---|---|---|---|---|
Chrome |
Chromium、<br/>Blink | V8 | -webkit- |
|
Safari |
Apple | Webkit | JScore、<br/>SquirrelFish(Nitro)(4.0+) | -webkit- |
FireFox |
Mozilla | Gecko | SpiderMonkey(1.0-3.0)、<br/>TraceMonkey(3.5-3.6)、<br/>JaegerMonkey(4.0+) | -moz- |
Opera |
OperaSoftware | Presto、<br/>Webkit、<br/>Blink | Linear A(4.0-6.1)、<br/>Linear B(7.0-9.2)、<br/>Futhark(9.5-10.2)、<br/>Carakan(10.5-) | -o- |
IE |
Microsoft | Trident | JScript(IE9-)、<br/>Chakra(IE9+) | -ms- |
Edge |
Microsoft | EdgeHTML | Chakra | -ms- |
新 Edge |
Microsoft | Chromium | V8 | -webkit- |
UC |
阿里巴巴 | U3 | U3 集成? | 同红芯浏览器一样换汤不换药 |
360/QQ/ 搜狗 / 猎豹 、<br/> 百度 /2345/ 傲游 / 世界之窗 |
见下文 | Trident(兼容模式)+Webkit(高速模式)双内核 | / | 能用就行 |
- Chrome 以前是 Chromium 内核(Chrome 内核),在 Webkit 根底上批改,但代码可读性更高,比 Webkit 更好用。目前是应用从新升级换代后的 Blink 内核。谷歌还开发了本人的 JS 引擎 V8,使 JS 运行速度极大地提高,Node.js 也是以 V8 为底层架构封装。另外咱们能够通过在地址栏输出
chrome://version/
来查看浏览器相干信息,通过chrome://dino
玩小游戏。 - Safari 的 Webkit 源自 KHTML,苹果在比拟了 Gecko 和 KHTML 后,抉择了后者来做引擎开发,是因为 KHTML 领有清晰的源码构造和极快的渲染速度。苹果与谷歌抵触又研发应用 Webkit2 内核,谷歌则研发了 Chromium 内核,Webkit 也算是苹果为业界做出的最大奉献。
- FireFox 的 Gecko 内核俗称 Firefox 内核,代码齐全公开,可开发水平高,全世界的程序员都可为其编写代码,减少其性能。还有一个 JS 引擎 Rhino,也是由 Mozilla 基金会治理,尽管最终被废除,但其凋谢源代码,齐全以 Java 编写。
- Opera 最早本人研发 Presto,前面用 Webkit,最初与谷歌一起公布应用 Blink,而后因用户体验降落逐步衰败。
- IE 是微软和 Spyglass 合作开发,随 Windows 绑定抢占市场,并且只能在 Windows 应用也不开源。
- Edge 原名叫斯巴达,后改名 Edge,2015 年 3 月公布第一个预览版。微软打算在 Windows 中齐全淘汰 Internet Explorer 后,为 Edge 增加“IE 模式”,该模式容许用户在 Edge 内应用 IE 内核从新加载网页。
- 新 Edge 是微软斗争下的产物,2018 年 12 月发表新 Edge 将基于 Chromium 内核开发,正式版于 2020 年 1 月公布。能够通过
edge://version/
来查看浏览器版本信息,通过edge://surf/
能够玩离线小游戏。 - UC 浏览器的 U3 内核实质是基于开源内核 Webkit 开发,也有说是基于 Gecko 内核与 Trident 内核开发的。
- 泛滥国产浏览器的厂商别离为 360 平安、Tencent、搜狗信息、豹好玩科技、Baidu、二三四五、网际傲游、凤凰工作室。这些浏览器适宜须要常常拜访那种古老零碎的用户(兼容模式)
补充:还有一个 JS 引擎 – KJS,KDE 的 ECMAScript/JavaScript 引擎,最后由哈里·波顿开发,用于 KDE 我的项目的 Konqueror 网页浏览器中。
浏览器的原理
浏览器程序结构
- 用户界面(User Interface) – 包含地址栏、后退 / 后退按钮、书签菜单等。除了浏览器主窗口(显示页面),其余局部都属于用户界面。
- 浏览器引擎(Browser Engine) – 在用户界面和渲染引擎之间传送指令。
- 渲染引擎(Rendering Engine) – 显示(渲染)申请的内容。如果申请的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。
- 网络(NetWorking) – 用于网络调用,比方 HTTP 申请。其接口与平台无关,并为所有平台提供底层实现。
- JavaScript 解释器(JavaScript Interpreter)。用于解析和执行 JavaScript 代码。
- 用户界面后端(UI Backend) – 用于绘制根本的窗口小部件,比方组合框和窗口。公开了与平台无关的通用接口,在底层应用操作系统的用户界面办法。
- 数据存储(Data Persistence) – 这是长久层。浏览器须要在硬盘上保留各种数据,例如 Cookie。新的 HTML 标准 (HTML5) 定义了“网络数据库”,这是一个残缺(然而轻便)的浏览器内数据库。
浏览器程序结构倒退
-
最早的浏览器上单过程构造,页面线程执行页面渲染,JS 线程执行 JS 代码等等,然而只有其中一个线程出问题,可能整个程序就解体了。
- 例如:浏览器的一个标签页卡死,那么整个浏览器都无奈应用,导致应用程序极其不稳固。
- 单过程是能够共享数据的,所以并不平安。
- 因为各个线程负责的工作过多,应用起来也并不晦涩。
-
为了解决这些问题,古代浏览器应用了多过程构造。可分为浏览器过程、网络过程、缓存过程、GPU 过程、渲染器过程、插件过程。
- 浏览器过程:管制用户界面,协调其余过程工作。
- 网络过程:发动接管网络申请
- 缓存过程:控制数据缓存
- GPU 过程:负责浏览器界面与页面的渲染
- 渲染器过程:管制 Tab 标签页的渲染,有可能会为每个标签页创立一个渲染过程(由浏览器启动模型决定)。独立每个页面一个过程能够起到过程隔离的作用,每个页面互不烦扰。
- 插件过程:管制应用的插件,Flash 等等,不是浏览器装置的插件。
渲染主流程
- 浏览器从网络层获取申请的文档内容,而后开始渲染流程。
- 解析并开始构建 Content Tree(Element -> DOM nodes),同时解析款式数据(内部 CSS 和 Style 元素)。
- 两者联合构建 Render Tree(渲染树蕴含带有视觉属性(如色彩和尺寸)的矩形们)。
- 在渲染树创立后进入 Layout 阶段,给渲染树的每个节点设置在屏幕上的地位信息。
- Paint 阶段,通过 UI backend 绘制 Render tree 到屏幕。
留神,渲染过程是渐进式的。浏览器会尽早展现文档内容,即不会在所有 HTML 文档解析实现后才会去构建 Render tree,而是局部内容被解析和展现,并持续解析和展现剩下的。
浏览器的页面渲染过程
参考文章
-
在浏览器地址栏输出 URL
-
浏览器会启动网络线程来申请 DNS 进行域名解析,最终返回一个 IP 地址。
-
一旦获取到服务器 IP 地址,浏览器就会通过 TCP【三次握手】与服务器建设连贯。这个机制的是用来让两端尝试进行通信。浏览器和服务器在发送数据之前,通过下层协定 HTTPS 能够协商网络 TCP 套接字连贯的一些参数。TCP 的【三次握手】技术常常被称为【SYN-SYN-ACK】,更确切的说是【SYN, SYN-ACK, ACK】,因为通过 TCP 首先发送了三个音讯进行协商,开始一个 TCP 会话在两台电脑之间。这意味着服务器之间还要来回发送三条音讯,而咱们的申请目前尚未收回。
-
上图咱们能够这样了解,因为 TCP 是一个工作在传输层的牢靠数据传输的服务,它能确保接收端接管的网络包是无损坏、无距离、非冗余和按序的。
- 面向连贯:肯定是「一对一」能力连贯,不能像 UDP 协定能够一个主机同时向多个主机发送音讯,也就是一对多是无奈做到的。
- 牢靠的:无论的网络链路中呈现了怎么的链路变动,TCP 都能够保障一个报文肯定可能达到接收端。
- 字节流:音讯是「没有边界」的,所以无论咱们音讯有多大都能够进行传输。并且音讯是「有序的」,当「前一个」音讯没有收到的时候,即便它先收到了前面的字节,那么也不能扔给应用层去解决,同时对「反复」的报文会主动抛弃。
- 参考:ibanmen
-
TCP 是面向连贯的协定,所以应用 TCP 前必须先建设连贯,而建设连贯是通过三次握手来进行的,简略解释上图能够是:
- 我对你说:我要跟你谈话。(此时服务端确认客户端的发送能力没有问题)
- 你跟我说:我晓得你要跟我谈话,咱们开始谈话吧。(此时客户端确认服务端的接管和发送能力都没有问题)
-
我跟你说:好的,咱们开始谈话吧。(此时服务端确认客户端的接管能力也没有问题)
-
-
TLS/SSL 协商:为了在【HTTPS】上建设平安连贯,另一种握手是必须的。更确切的说是 TLS/SSL 协商,它决定了什么明码将会被用来加密通信,验证服务器,这就意味着在进行实在的数据传输之前建设平安连贯。在发送真正的申请内容之前还须要三次往返服务器。尽管建设平安连贯对减少了加载页面的等待时间,对于建设一个平安的连贯来说,以减少等待时间为代价是值得的,因为在浏览器和 web 服务器之间传输的数据不能够被第三方解密。
-
通过上图 8 次往返,浏览器终于能够发出请求。一旦咱们建设了到 web 服务器的连贯,浏览器就代表用户发送一个初始的 HTTP GET 申请,对于网站来说,这个申请通常是一个 HTML 文件。
-
一旦服务器收到申请,它将应用相干的响应头和 HTML 的内容进行回复。此时网络线程会告诉 UI 线程执行后续操作。
-
UI 线程会创立一个渲染器过程来渲染页面,浏览器过程会通过 IPC 管道将数据传递给渲染器过程。
-
渲染器过程的主线程接管到数据(HTML),开始渲染解析。
-
通过标签词法解析,将内容解析为多个标记,而后结构 DOM 树,先创立 document 对象,再一直批改,向其中增加各种元素。
-
解析引入的 css、js、img 等等,图片与 css 不会阻塞 HTML 的解析,因为不影响 DOM 树的结构。但
<script>
标签会阻塞 HTML 的解析,转而执行其中的 js 代码,因为浏览器不分明此 js 代码是否有扭转 DOM 构造,所以后行执行。
-
-
构建 DOM 树后,主线程开始解析 css 并确定每个 DOM 节点的款式,即便咱们没写款式,每个浏览器都有本人的样式表。
-
构建 LayoutTree,通过 DOM 树和款式生成 LayoutTree,即确定每个节点的地位。LayoutTree 的每个节点都记录了本人的坐标与边框尺寸等。
- DOM 树与 Layout 树并不是对应的,设置了
display:none;
的节点是不会在 Layout 树中。 -
有内容显示的伪元素节点不会呈现在 DOM 树中,但会呈现在 Layout 树中,因为 DOM 是通过 HTML 解析的,而伪元素是通过款式产生的。
- DOM 树与 Layout 树并不是对应的,设置了
-
渲染器过程的主线程遍历 LayoutTree 确定各个节点的绘制程序,创立一个绘制记录表(Paint Record)。比方
z-index
值大的元素个别都是最初绘制等等。 -
渲染器过程的主线程再遍历 LayoutTree 生成 Layer Tree。
-
渲染器过程的主线程将 Layer Tree 与绘制程序表一起传给合成器线程。
- 合成器线程按规定进行分图层,并把图层生成更小的图块 (tiles) 再传递给栅格线程进行栅格化。
- 栅格化实现后返还给合成器线程 draw quads 图块信息(每图块的信息与地位等)。
- 合成器线程依据这些 draw quads 信息用 frame 合成器将合成一个合成器帧。
- 再通过 IPC 管道将此合成器帧传递给浏览器过程。
- 浏览器过程收到这帧的图像后传递给 GPU,GPU 渲染到页面上。
- 当你滚动页面时又会从新生成合成器帧,再次渲染到页面上。
- 当咱们扭转元素地位或尺寸属性时,会从新进行款式计算、布局、绘制等前面所有流程(重排 -reflow)。
- 当咱们只扭转色彩这种属性时,不会引起从新触发布局,会触发款式计算与绘制(重绘 -repaint)。
- 因为 JS 也是在主线程运行,所以尽量不要高频触发重绘重排,毕竟布局、绘制也是在占用主线程,高频触发重绘重排会导致页面掉帧。
- 所以尽量减少重绘重排,能够转而应用 CSS3 的 transform 动画来达到成果(会间接运行合成器线程),这些是不会占用主线程的,可能防止重绘重排与 js 执行争夺主线程导致页面卡顿掉帧的问题。
- 在挪动端应用 3D 转换能够优化性能。如果设施有 3D 减速引擎 GPU 能够进步性能,2D 转换是无奈调用 GPU,2D 是靠的 CPU。
-
也能够利用
requestAnimationFrame()
API,利用浏览器的闲暇工夫来优化,React Fiber 就是应用此 API,他会将主线程的工作扩散到每一帧的距离,从而不影响动画的流程。
-
收到全部内容之后能够抉择断开 (依据 Connection 申请头,若为 keep-alive 则放弃。) 与服务器之间的 TCP 连贯。
- 我对你说:好了,我不想跟你谈话了,再见。(客户端发送敞开连贯申请给服务端)
- 你对我说:好的,那我要跟你再见啦。(服务端确认客户端的申请)
- 你对我说:当初我要跟你再见了,你晓得了吗。(服务端申请敞开连贯)
-
我对你说:我晓得了,再见!(客户端确认申请)
浏览器页面的优化
性能优化
- 缩小 DNS 查找(应用 cdn 等)
- js 提早加载或异步加载
- 尽量应用 link,缩小应用 @import,import 是最初挂载的。
- 缩小 HTTP 申请(CSS Sprite、合并 css、合并 js 等等)
- 将 html/css/js/img 等文件压缩
- 开启 gzip 模块
- 长于开启并利用缓存,从缓存中读取图片与 html/css/js 等。
-
增加 Expires 头缓存
-
页面的首次访问者会进行很多 HTTP 申请,然而通过应用一个短暂的 Expires 头,能够使这些组件被缓存,下次访问的时候,就能够缩小不必要的 HTPP 申请,从而进步加载速度。
- Web 服务器通过 Expires 头通知客户端能够应用一个组件的以后正本,直到指定的工夫为止。
- 例如:
Expires: Fri, 18 Mar 2016 07:41:53 GMT
- Expires 毛病: 它要求服务器和客户端时钟严格同步,过期日期须要常常查看。
- HTTP1.1 中引入 Cache-Control 来克服 Expires 头的限度,应用 max-age 指定组件被缓存多久。
Cache-Control: max-age=12345600
- 若同时制订 Cache-Control 和 Expires,则 max-age 将笼罩 Expires 头。
-
-
HTML 代码优化
- 应用语义化的标签,代码清晰简洁。
- 应用 W3C 规范书写闭合小写的标签。
- 防止应用空申请,包含空的 href 链接、空 src 链接。空链接自身无奈申请胜利,因而会把一个 HTTP 申请拖到超时,而且空链接会阻塞页面中其余资源的下载过程,会拖慢页面加载速度。
- 依据我的项目大小,抉择次要应用 class 还是 id。id 选择器优先级最高,访问速度最快。然而在 html 中每申明一个 id,就会在 js 底层申明一个全局变量,而全局变量的增多,将会拖慢 js 中变量遍历的效率,举荐我的项目小能够用 id,我的项目大少用 id。
- 事后设定图片与 table 大小,防止缩放。在页面加载过程中,图片最初加载,若不对图片预设大小,当图片加载实现后,将会引起大量的重排,将会节约浏览器资源及拖慢页面加载速度。
- 尽量减少 DOM 元素的数量与层级。解析 HTML 时,标签的数量越多,标签的层级越深,浏览器解析构建 DOM 树的工夫就越长,应尽可能的缩小 DOM 元素的数量和层级。
- 尽量避免应用 table 标签。浏览器对 table 标签的解析是全副生成后再一次性绘制的,因而会造成表格地位较长时间的空白,举荐应用 ul 及 li 标签绘制表格。
- 应用异步加载 iframe 标签。浏览器加载 iframe 标签时,会阻塞父页面渲染树的构建及 HTTP 申请,因而尽量应用异步加载 iframe。
-
CSS 代码优化
-
禁止应用款式表达式,它的解析速度较慢,而且运算次数远比咱们设想的要大,随便动动鼠标就能轻松达到上万次运算,会对页面性能造成影响。
- 例如:
#myDiv{width: expression(document.body.offsetWidth-110+"px");}
。
- 例如:
- 优化要害选择器,去掉有效的父级选择器,尽量少在选择器开端应用通配符。大多数人都认为,浏览器对 CSS 选择器的解析式从左往右进行的,然而其实是从右到左执行的。
- 缩小有效代码,留神专用款式。
-
-
JS 代码优化
- 多个 js 变量申明合并。
- 不应用 eval 函数,不平安,性能耗费重大。
- 应用事件代理绑定事件,如将事件绑定到 body 上进行代理,利用冒泡原理将事件加到父级上,可能给动静减少的元素进行数据绑定。
- 防止频繁的操作 DOM 节点,应用 innerHTML 代替,从而缩小重绘和重排。
- 缩小全局变量,尽量应用局部变量。js 中全局变量运算速率远低于局部变量,速度差别达到上百倍,且全局变量越多,全局变量的查找速率便越慢。
- 缩小 js 对 css 款式的批改从而缩小重绘和重排。
- 缩小 ajax 申请,罕用数据存本地。
- LazyLoad Images
兼容性优化
- HTML5 新的语义标签在低版本的老 IE 浏览器中存在兼容性问题,能够引入第三方解析库。
<script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
- 应用 Reset CSS 来对立浏览器款式
- 不必兼容 IE 时,间接排除掉。
- 写 CSS3 新款式属性时,加浏览器前缀兼容晚期浏览器。
@keyframes | |
transform | |
transtion | |
animation | |
border-radius | |
box-shadow | |
flex | |
... |
- 防止应用不兼容的 js 代码(工夫解决问题、屏幕宽高问题、event 事件问题、DOM 节点问题、事件流传问题、阻止默认事件问题、鼠标滚轮滚动事件问题等等)。
- 鼠标指针
cursor: hand;
只有 IE 浏览器辨认,其余浏览器不辨认。对立应用cursor: pointer;
- 超链接拜访过后 hover 款式就不呈现的问题,须要留神伪类程序
link-visited-hover-active
。 - css hack
background-color: yellow0; // 0 ie8 | |
+background-color: pink; // + ie7 | |
_background-color: orange; // _ ie6 |
- 应用一个性能之前判断浏览器是否反对,比方应用 ajax 要判断是否反对 XMLHttpRequest,IE6 之前不反对。还有应用本地存储、告诉弹窗等 HTML5 新个性时更须留神。
参考起源
- 参考 HTML 引擎)
- 参考 JavaScript 引擎
- 参考浏览器原理