感觉知识点有点浅,在后期优化吧
1仅打开了 1 个页面,为什么有 4 个进程?
单进程的
缺点:不稳定、不流畅且不安全
多进程浏览器时代
- 浏览器进程。
主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。 - 渲染进程。
核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。 - GPU 进程。
其实,Chrome 刚开始发布的时候是没有 GPU 进程的。而 GPU 的使用初衷是为了实现 3D CSS 的效果,只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求。最后,Chrome 在其多进程架构上也引入了 GPU 进程。 - 网络进程。
主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程。 - 插件进程。
主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。
不过凡事都有两面性,虽然多进程模型提升了浏览器的稳定性、流畅性和安全性,但同样不可避免地带来了一些问题:
- 更高的资源占用。因为每个进程都会包含公共基础结构的副本(如 JavaScript 运行环境),这就意味着浏览器会消耗更多的内存资源。
- 更复杂的体系架构。浏览器各模块之间耦合性高、扩展性差等问题,会导致现在的架构已经很难适应新的需求了
面向服务架构(SOA)形式
2TCP协议:如何保证页面文件能被完整送达浏览器?
互联网中的数据是通过数据包来传输的,数据包在传输过程中容易丢失或出错。
- IP 负责把数据包送达目的主机。
- UDP 负责把数据包送达具体应用。
- 而 TCP 保证了数据完整地传输,它的连接可分为三个阶段:建立连接、传输数据和断开连接。
虽说 UDP 不能保证数据可靠性,但是传输速度却非常快,所以 UDP 会应用在一些关注速度、但不那么严格要求数据完整性的领域,如在线视频、互动游戏等。
tcp和udp都是传输层协议,通常二选一
tcp传送数据时 浏览器端就做渲染处理了么?如果前面数据包丢了 后面数据包先来是要等么?类似的那种实时渲染怎么处理?针对数据包的顺序性?
接收到http响应头中的content-type类型时就开始准备渲染进程了, 响应体数据一旦接受到便开始做DOM解析了!
基于http不用担心数据包丢失的问题,因为丢包和重传都是在tcp层解决的。
http能保证数据按照顺序接收的!
你怎么理解 HTTP 和 TCP 的关系?
HTTP协议和TCP协议都是TCP/IP协议簇的子集。
HTTP协议属于应用层,TCP协议属于传输层,
HTTP协议位于TCP协议的上层。
请求方要发送的数据包,在应用层加上HTTP头以后会交给传输层的TCP协议处理,应答方接收到的数据包,在传输层拆掉TCP头以后交给应用层的HTTP协议处理。建立 TCP 连接后会顺序收发数据,请求方和应答方都必须依据 HTTP 规范构建和解析HTTP报文。
3为什么很多站点第二次打开速度会很快?
- DNS 缓存:主要就是在浏览器本地把对应的 IP 和域名关联起来
- 页面资源缓存
- 注意事项
-
是否要使用localstorage,还是要看具体应用场景。其实使用cookie会很方便,因为它会随着http请求头把cookie内容发送服务器,用localstorage需要重新实现数据上传和下载。
-
一个http中的keep-alive是排队请求,也就是一个http请求完成之后才能继续请求下一个,而http2中请求是并发的,可以同时处理很多请求!
-
”同一个域名同时最多只能建立 6 个 TCP 连接“ 指的不光是指Ajax,还包括页面中的资源加载,只要是一个域名下的资源,浏览器同一时刻最多只支持6个并行请求。 不过这是HTTP/1.1的规则,HTTP/2已经不用这套规则了,而且HTTP/2也很成熟了,有条件可以考虑切换到HTTP/2. Ajax其实就是HTTP请求,包括了XMLHttpRequest和Fetch,HTTP请求是建立在TCP协议之上的。
4从输入URL到页面展示,这中间发生了什么?
从用户输入URL到浏览器展示最终页面,需要浏览器进程、网络进程、渲染进程三者之间相互配合完成。
首先浏览器读取用户的输入内容,假如不是完整的URL链接,浏览器会将输入内容定义为搜索内容,由默认的搜索引擎配合构成完整的搜索URL;那如果是一个完整的URL链接,浏览器进程就开启整个导航流程,在发起URL请求之前,浏览器进程还给页面提供了beforeUnload事件,用于页面决定是否需要取消即将发起的请求。如果没有取消,流程继续,浏览器进程发起URL请求,这时候交由网络进程完成HTTP请求部分工作,网络进程首先构建请求,
然后检查浏览器本地是否已经有缓存,有缓存并且缓存没有过期,则直接返回缓存内容,否则继续请求流程,这里通过Cache-control字段判断缓存是否过期,如果过期了,HTTP请求头中会发送If-Not-Match字段来告诉服务器当前本地存放的缓存信息。查找缓存阶段结束后
,网络进程中首先由DNS解析URL获得IP和端口号,IP负责指向服务器地址,端口号负责指向同哪个应用通信。然后即将建立TCP连接,当然在连接建立之前,如果是HTTP/1.1协议,还需要判断当前TCP队列是否有空闲,HTTP1.1默认可以建立6个TCP连接,如果队列刚好空闲,还要判断协议是否是HTTPS,如果是,还需要先建立TLS连接,然后才是建立TCP连接,三次握手,然后服务端开始传输数据,TCP为了保证传输数据的完备性,在传输阶段每个数据包都会给服务器返回确认包,如果一定时间内,服务器没收到某个数据包的确认包,证明该数据包丢失,服务器需要重新发送,当所有数据包处理完成,网络进程将响应头和响应体返回,网络进程通过IPC通信告知浏览器进程,
准备渲染进程,然后将响应体信息中的HTML信息提交给渲染进程,最后由渲染进程完成整个页面的渲染。
渲染流程
结合上图,一个完整的渲染流程大致可总结为如下:
- 渲染进程将 HTML 内容转换为能够读懂的 DOM 树结构。
- 渲染引擎将 CSS 样式表转化为浏览器可以理解的 styleSheets,计算出 DOM 节点的样式。
- 创建布局树,并计算元素的布局信息。
- 对布局树进行分层,并生成分层树。
- 为每个图层生成绘制列表,并将其提交到合成线程。
- 合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图。
- 合成线程发送绘制图块命令 DrawQuad 给浏览器进程。
- 浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上。
合成层性能优化点:
- 提升动画效果的元素 合成层的好处是不会影响到其他元素的绘制,因此,为了减少动画元素对其他元素的影响,从而减少paint,我们需要把动画效果中的元素提升为合成层。
提升合成层的最好方式是使用 CSS 的 will-change属性。从上一节合成层产生原因中,可以知道 will-change 设置为opacity、transform、top、left、bottom、right 可以将元素提升为合成层。 - 使用 transform 或者 opacity 来实现动画效果, 这样只需要做合成层的合并就好了。
- 减少绘制区域 对于不需要重新绘制的区域应尽量避免绘制,以减少绘制区域,比如一个 fix 在页面顶部的固定不变的导航header,在页面内容某个区域 repaint 时,整个屏幕包括 fix 的 header 也会被重绘。
而对于固定不变的区域,我们期望其并不会被重绘,因此可以通过之前的方法,将其提升为独立的合成层。减少绘制区域,需要仔细分析页面,区分绘制区域,减少重绘区域甚至避免重绘。
利用合成层可能踩到的坑
- 合成层占用内存的问题
- 层爆炸,由于某些原因可能导致产生大量不在预期内的合成层,虽然有浏览器的层压缩机制,但是也有很多无法进行压缩的情况,这就可能出现层爆炸的现象(简单理解就是,很多不需要提升为合成层的元素因为某些不当操作成为了合成层)。解决层爆炸的问题,最佳方案是打破 overlap 的条件,也就是说让其他元素不要和合成层元素重叠。简单直接的方式:
使用3D硬件加速提升动画性能时,最好给元素增加一个z-index属性,人为干扰合成的排序,可以有效减少chrome创建不必要的合成层,提升渲染性能,移动端优化效果尤为明显。
比如 页面中设置了一个h1标题,应用了translate3d动画,使得它被放到composited layer中渲染,然后在这个元素后面创建了2000个list。在不为h1元素设置z-index的情况下,使得本不需要提升到合成层的ul元素下的每个li元素都提升为一个单独合成层(每个li元素的黄色提示边框),最终会导致GPU资源过度消耗页面滑动时很卡,尤其在移动端(安卓)上更加明显。
如上图操作选中
为动画元素设置z-index,可以看出ul下的每个li都回归到普通渲染层,不再是合成层也就不会消耗GPU资源去渲染,从而达到了优化页面性能优化的目的。大家可以用支持『硬件加速』的『安卓』手机浏览器测试上述页面,给动画元素加z-index前后的性能差距非常明显。