共计 4830 个字符,预计需要花费 13 分钟才能阅读完成。
1 一道面试题开展
进行前端面试时,常常问这样一个问题:从浏览器地址栏输出 URL 后,到页面渲染进去,整个过程都产生了什么?
不堪一击的答复:首先浏览器发动申请,而后服务器返回数据,最初脚本执行和页面渲染。如果你的答复与下面的相差不大,就阐明对前端性能优化还没有什么概念。
其实这个问题的答复能够十分粗疏,能从信号与零碎、计算机原理、操作系统聊到网络通信、浏览器内核,再到 DNS 解析、负载平衡、页面渲染等多个层面答复,每个层面开展都是一个独立的章节。
这里只思考前后端相干内容,能够划分为以下几个阶段:
1,浏览器接管到 URL,到网络申请线程的开启。
2,一个残缺的 HTTP 申请的收回。
3,服务器接管到申请并转到具体的解决后盾。
4,前后台之间的 HTTP 交互和波及的缓存机制。
5,浏览器接管到数据包后的要害渲染门路。
6,JS 引擎的解析过程。
2 网络线程的开启
想要搞清楚这个阶段是怎么回事,先来理解下线程和过程。
a 线程和过程
简略来说,过程就是一个程序运行的实例,操作系统会为过程创立独立的内存,用来寄存运行所需的代码和数据;而线程是过程的组成部分,每个过程至多有一个主线程及可能的若干子线程,这些线程由所属的过程进行启动和治理。因为多个线程能够共享操作系统为其所属的同一个过程所调配的资源,所以多线程的并行处理能无效进步程序的运行效率。如图:
特点:
(1)只有某个线程执行出错,将会导致整个过程解体。
(2)过程与过程之间互相隔离。这保障了当一个过程挂起或解体的状况产生时,并不会影响其余过程的失常运行,尽管每个过程只能拜访零碎调配给本人的资源,但能够通过 IPC 机制进行过程间通信。
(3)过程所占用的资源会在其敞开后由操作系统回收。即便过程中存在某个线程产生的内存透露,当过程退出时,相干的内存资源也会被回收。
(4)线程之间能够共享所属过程的数据。
问题:浏览器应该是多过程还是单过程呢?
你能够点击 Chrome 浏览器右上角的“选项”菜单,抉择“更多工具”子菜单,点击“工作管理器”
能够看到多个过程在运行,浏览器为什么不应用单过程?
b 单过程浏览器
在 2008 年谷歌公布 Chrome 多过程浏览器之前,市面上简直所有浏览器都是单过程的,它们将所有功能模块都运行在同一个过程中,如下图所示:
设想一下这样的解决形式会存在什么问题,一个过程下关上多个页面,多个窗口,内存会怎么?如果其中一个页面解体了,又会产生什么?一些比拟显著的隐患裸露如下:
● 流畅性:首先是页面内存透露,浏览器内核通常非常复杂,单过程浏览器关上再敞开一个页面的操作,通常会有一些内存不能齐全回收,这样随着应用工夫缩短,占用的内存会越来越多,从而引起浏览器运行变慢;其次因为很多模块运行在同一个线程中,如 JS 引擎、页面渲染及插件等,那么执行某个循环工作的模块就会阻塞其余模块的工作执行,这样难免会有卡顿的景象产生。
● 安全性:因为插件的存在,未免其中有些歹意脚本会利用浏览器破绽来获取零碎权限,进行引发平安问题的行为。
● 稳定性:因为所有模块都运行在同一个过程中,对于稍简单的 JS 代码,如果页面渲染引擎解体,就会导致整个浏览器解体。同样,各种不稳固的第三方插件,也是导致浏览器解体的隐患。
c 多过程浏览器
出于对单过程浏览器存在问题的优化,Chrome 推出了多过程浏览器架构,如图:
(1)浏览器主过程:一个浏览器只有一个主过程,负责如菜单栏、标题栏等界面显示,文件拜访,后退后退,以及子过程治理等。
(2)GPU 过程:GPU(图形处理单元)最后是为了实现 3D 的 CSS 成果而引入的,起初随着网页及浏览器在界面中的应用需要越来越广泛,Chrome 便在架构中退出了 GPU 过程。能够用来进步动画渲染性能。
(3)插件过程:主过程会为每个退出浏览器的插件开拓独立的子过程,因为过程间所调配的运行资源绝对独立,所以即使某个插件过程意外解体,也不至于对浏览器和页面造成影响。另外,出于对平安因素的思考,这里采纳了沙箱模式,在沙箱中运行的程序受到一些限度:不能读取敏感地位的数据,也不能在硬盘上写入数据。这样即便插件运行了歹意脚本,也无奈获取零碎权限。
(4)网络过程:负责页面的网络资源加载,之前属于浏览器主过程中的一个模块,最近才独立进去。
(5)渲染过程:也称为浏览器内核,其默认会为每个标签窗口页开拓一个独立的过程,负责将 HTML、CSS 和 JavaScript 等资源转为可交互的页面,其中蕴含多个子线程,即 JS 引擎线程、GUI 渲染线程、事件触发线程、定时触发器线程、异步 HTTP 申请线程等。当关上一个标签页输出 URL 后,所发动的网络申请就是从这个过程开始的。另外,出于对安全性的思考,渲染过程也被放入沙箱中。
多个过程之间是如何合作的?
- 首先,用户从浏览器过程里 输出申请信息(浏览器过程次要负责用户交互)
- 而后,网络过程 发动 URL 申请;(网络过程向渲染过程和浏览器过程等提供网络下载性能)
- 服务器响应 URL 申请之后,浏览器过程就又要开始 筹备渲染过程 了;
- 渲染过程筹备好之后,须要先向渲染过程提交页面数据,咱们称之为 提交文档 阶段;
- 渲染过程接管完文档信息之后,便开始 解析页面和加载子资源,实现页面的渲染。
网络过程开启后,首先要解析 url:
3 建设 HTTP 申请
次要工作是 DNS 解析和通信链路的建设,艰深点将就是我要晓得须要申请资源的服务器地址。因为域名不是服务器地址是,能够了解为器地址的别名。
a DNS 解析
首先查问浏览器本身的 DNS 缓存,如果查到 IP 地址就完结解析,因为缓存工夫限度比拟大,个别只有 1 分钟,同时缓存容量也有限度,所以在浏览器缓存中没找到 IP 地址时,就会搜寻零碎本身的 DNS 缓存;如果还未找到,接着就会尝试从零碎的 hosts 文件中查找。
在本地主机进行的查问若都没获取到,接下来便会在本地域名服务器上查问。如果本地域名服务器没有间接的指标 IP 地址可供返回,则本地域名服务器便会采取迭代的形式去顺次查问根域名服务器、COM 顶级域名服务器和权限域名服务器等,最终将所要拜访的指标服务器 IP 地址返回本地主机,若查问不到,则返回报错信息。
解析过程如下:
b 网络模型
国际标准化组织提出了一些网络架构模型:OSI 模型、TCP/IP 模型,二者的网络模型图示如图:
TCP/IP 模型宽泛应用,成为目前互联网事实上的规范。
c TCP 链接
传输层常见的协定有 TCP 协定和 UDP 协定,这里简略介绍 TCP 协定的“三次握手”和“四次挥手”。
这里用图来示意“三次握手”过程:
四次挥手
链接建设好当前,就能够进行前后端交互了。
4 前后端交互
当 TCP 连贯建设好之后,便可通过 HTTP 等协定进行前后端的通信,但在理论的网络拜访中,并非浏览器与确定 IP 地址的服务器之间间接通信,往往会在两头退出反向代理服务器。
a 反向代理
反向代理服务器依据客户的申请,从后端服务器上获取资源后提供给客户端。反向代理服务器通常的作用如下:
● 负载平衡。
● 平安防火墙。
● 加密及 SSL 减速。
● 数据压缩。
● 解决跨域。
● 对动态资源缓存。
直观图:
b 后端解决流程
(1)首先会有一层对立的验证环节,如跨域验证、平安校验拦挡等。如果发现是不合乎规定的申请,则间接返回相应的回绝报文。
(2)通过验证后才会进入具体的后台程序代码执行阶段,如具体的计算、数据库查问等。
(3)实现计算后,后盾会以一个 HTTP 响应数据包的模式发送回申请的前端,完结本次申请。
c HTTP 相干协定
HTTP 2.0 到来之前,每一个资源的申请都须要开启一个 TCP 连贯,因为 TCP 自身有并发数的限度,这样的后果就是,当申请的资源变多时,速度性能就会显著降落。为此,常常会采纳的优化策略包含,将动态资源的申请进行多域名拆分,对于小图标或图片应用雪碧图等。
在 HTTP 2.0 之后,便能够在一个 TCP 连贯上申请多个资源,宰割成更小的帧申请,其速度性能便会显著回升,所以之前针对 HTTP 1.1 限度的优化计划也就不再须要了。
HTTP 2.0 除了一个连贯可申请多个资源这种多路复用的个性,还有如下一些新个性。
(1)二进制分帧:在应用层和传输层之间,新退出了一个二进制分帧层,以实现低提早和高吞吐量。
(2)服务器端推送:以往是一个申请带来一个响应,当初服务器能够向客户端的一个申请收回多个响应,这样便能够实现服务器端被动向客户端推送的性能。
(3)设置申请优先级:服务器会依据申请所设置的优先级,来决定须要多少资源解决该申请。
(4)HTTP 头部压缩:缩小报文传输体积。
d 浏览器缓存
次要分为强缓存和协商缓存,在前后端交互的过程中,应用缓存能够显著的进步性能,前面会做具体介绍。
链接建设好当前,服务端须要向客户端发送文件,在这个过程中,能够将一些文件缓存到本地,进步申请的响应速度。
强缓存标识:
600 再次申请改文件间接应用本地缓存,如果么有 max-age 则 expries 失效,这是个绝对工夫,在这个工夫达到之前,申请该文件应用本地缓存。绝对工夫的毛病是不精准,客户端零碎工夫能够更改。
协商缓存:
如果没有强制缓存标识或者强制缓存到期,查看是否有协商缓存标识:
Last-Modified / If-Modified-Since
Last-Modified 是服务器响应申请时,返回该资源文件在服务器最初被批改的工夫,如下。
If-Modified-Since 则是客户端再次发动该申请时,携带上次申请返回的 Last-Modified 值,通过此字段值通知服务器该资源上次申请返回的最初被批改工夫。服务器收到该申请,发现申请头含有 If-Modified-Since 字段,则会依据 If-Modified-Since 的字段值与该资源在服务器的最初被批改工夫做比照,若服务器的资源最初被批改工夫大于 If-Modified-Since 的字段值,则从新返回资源
毛病:短时间内资源产生了扭转,Last-Modified 并不会发生变化。
Etag / If-None-Match(优先级较高)
Etag 是服务器响应申请时,返回以后资源文件的一个惟一标识(由服务器生成),如下。
If-None-Match 是客户端再次发动该申请时,携带上次申请返回的惟一标识 Etag 值,通过此字段值通知服务器该资源上次申请返回的惟一标识值。服务器收到该申请后,发现该申请头中含有 If-None-Match,则会依据 If-None-Match 的字段值与该资源在服务器的 Etag 值做比照,代表资源无更新,持续应用缓存文件。
5 要害门路渲染
a 构建模型
返回 html 文件后,须要对外面的 dom 和 css 进行解析,分为 html 解析和 css 解析,解析的过程其实就是构建 DOM 树的过程:
<!DOCTYPE html>
<html lang="en">
<head>
<link href="style.css" rel="stylesheet"/>
<title> 要害门路渲染 </title>
</head>
<body>
<p> 你好 <span> 性能优化 </span></p>
<div>
<img src='photo.jpg'/>
</div>
</body>
</html>
下面代码的解析为:
css 为:
body {font-size: 16px;}
p {font-weight: bold;}
span {color: red;}
p span {display: none;}
img {float: left;}
解析为:
b 渲染
(1)从所生成 DOM 树的根节点开始向下遍历每个子节点,疏忽所有不可见的节点(脚本标记不可见、CSS 暗藏不可见),因为不可见的节点不会呈现在渲染树中。
(2)在 CSSOM 中为每个可见的子节点找到对应的规定并利用。
(3)布局阶段,依据所失去的渲染树,计算它们在设施视图中的具体位置和大小,这一步输入的是一个“盒模型”。
(4)绘制阶段,将每个节点的具体绘制形式转化为屏幕上的理论像素。
以上为输出 url 后产生的一系列相干内容。后续的帖子安顿,就是选取本贴介绍的页面生命周期的某个部分环节进行优化,以及某些具体的优化技巧和实用工具。