关于浏览器:关于浏览器的那些事儿

1次阅读

共计 7503 个字符,预计需要花费 19 分钟才能阅读完成。

对于浏览器的那些事儿

七拼八凑了一些浏览器内容(^-^)

支流浏览器比照与倒退

  • 举荐一个短视频介绍
浏览器 / 参数 厂商 内核 JS 引擎 其余
Chrome Google 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(高速模式)双内核 / 能用就行
  1. Chrome 以前是 Chromium 内核(Chrome 内核),在 Webkit 根底上批改,但代码可读性更高,比 Webkit 更好用。目前是应用从新升级换代后的 Blink 内核。谷歌还开发了本人的 JS 引擎 V8,使 JS 运行速度极大地提高,Node.js 也是以 V8 为底层架构封装。另外咱们能够通过在地址栏输出 chrome://version/ 来查看浏览器相干信息,通过 chrome://dino 玩小游戏。
  2. Safari 的 Webkit 源自 KHTML,苹果在比拟了 Gecko 和 KHTML 后,抉择了后者来做引擎开发,是因为 KHTML 领有清晰的源码构造和极快的渲染速度。苹果与谷歌抵触又研发应用 Webkit2 内核,谷歌则研发了 Chromium 内核,Webkit 也算是苹果为业界做出的最大奉献。
  3. FireFox 的 Gecko 内核俗称 Firefox 内核,代码齐全公开,可开发水平高,全世界的程序员都可为其编写代码,减少其性能。还有一个 JS 引擎 Rhino,也是由 Mozilla 基金会治理,尽管最终被废除,但其凋谢源代码,齐全以 Java 编写。
  4. Opera 最早本人研发 Presto,前面用 Webkit,最初与谷歌一起公布应用 Blink,而后因用户体验降落逐步衰败。
  5. IE 是微软和 Spyglass 合作开发,随 Windows 绑定抢占市场,并且只能在 Windows 应用也不开源。
  6. Edge 原名叫斯巴达,后改名 Edge,2015 年 3 月公布第一个预览版。微软打算在 Windows 中齐全淘汰 Internet Explorer 后,为 Edge 增加“IE 模式”,该模式容许用户在 Edge 内应用 IE 内核从新加载网页。
  7. 新 Edge 是微软斗争下的产物,2018 年 12 月发表新 Edge 将基于 Chromium 内核开发,正式版于 2020 年 1 月公布。能够通过 edge://version/ 来查看浏览器版本信息,通过 edge://surf/ 能够玩离线小游戏。
  8. UC 浏览器的 U3 内核实质是基于开源内核 Webkit 开发,也有说是基于 Gecko 内核与 Trident 内核开发的。
  9. 泛滥国产浏览器的厂商别离为 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 等等,不是浏览器装置的插件。

渲染主流程

  1. 浏览器从网络层获取申请的文档内容,而后开始渲染流程。
  2. 解析并开始构建 Content Tree(Element -> DOM nodes),同时解析款式数据(内部 CSS 和 Style 元素)。
  3. 两者联合构建 Render Tree(渲染树蕴含带有视觉属性(如色彩和尺寸)的矩形们)。
  4. 在渲染树创立后进入 Layout 阶段,给渲染树的每个节点设置在屏幕上的地位信息。
  5. 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 前必须先建设连贯,而建设连贯是通过三次握手来进行的,简略解释上图能够是:

      1. 我对你说:我要跟你谈话。(此时服务端确认客户端的发送能力没有问题)
      2. 你跟我说:我晓得你要跟我谈话,咱们开始谈话吧。(此时客户端确认服务端的接管和发送能力都没有问题)
      3. 我跟你说:好的,咱们开始谈话吧。(此时服务端确认客户端的接管能力也没有问题)

  • 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 解析的,而伪元素是通过款式产生的。

  • 渲染器过程的主线程遍历 LayoutTree 确定各个节点的绘制程序,创立一个绘制记录表(Paint Record)。比方 z-index 值大的元素个别都是最初绘制等等。

  • 渲染器过程的主线程再遍历 LayoutTree 生成 Layer Tree。

  • 渲染器过程的主线程将 Layer Tree 与绘制程序表一起传给合成器线程。

    1. 合成器线程按规定进行分图层,并把图层生成更小的图块 (tiles) 再传递给栅格线程进行栅格化。
    2. 栅格化实现后返还给合成器线程 draw quads 图块信息(每图块的信息与地位等)。
    3. 合成器线程依据这些 draw quads 信息用 frame 合成器将合成一个合成器帧。
    4. 再通过 IPC 管道将此合成器帧传递给浏览器过程。
    5. 浏览器过程收到这帧的图像后传递给 GPU,GPU 渲染到页面上。
    6. 当你滚动页面时又会从新生成合成器帧,再次渲染到页面上。
    7. 当咱们扭转元素地位或尺寸属性时,会从新进行款式计算、布局、绘制等前面所有流程(重排 -reflow)。
    8. 当咱们只扭转色彩这种属性时,不会引起从新触发布局,会触发款式计算与绘制(重绘 -repaint)。
    9. 因为 JS 也是在主线程运行,所以尽量不要高频触发重绘重排,毕竟布局、绘制也是在占用主线程,高频触发重绘重排会导致页面掉帧。
    10. 所以尽量减少重绘重排,能够转而应用 CSS3 的 transform 动画来达到成果(会间接运行合成器线程),这些是不会占用主线程的,可能防止重绘重排与 js 执行争夺主线程导致页面卡顿掉帧的问题。
    11. 在挪动端应用 3D 转换能够优化性能。如果设施有 3D 减速引擎 GPU 能够进步性能,2D 转换是无奈调用 GPU,2D 是靠的 CPU。
    12. 也能够利用 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 引擎
  • 参考浏览器原理
正文完
 0