前端浏览器网络

193 阅读13分钟

关键字:回收机制、V8垃圾回收、内存泄漏、URL到页面渲染过程

一、浏览器进程与内核线程

image.png

(一)、浏览器是多进程的

浏览器是多进程的,有一个主进程,每打开一个tab都会新开一个进程(某请情况合并),进程主要包括:主进程、GPU、插件进程、渲染进程(内核)

  • Browser进程:浏览器主进程,负责协调主控,只有一个
  • 第三方插件进程:每个类型插件对应一个进程,仅当使用插件时创建。
  • GPU进程:用于3D绘制。
  • 渲染进程(内核):其内部是多线程的

(二)、浏览器内核是多线程的

  • GUI渲染线程:负责渲染浏览器界面,解析HTML、CSS,构建Dom树和RenderObject树,布局和绘制。GUI线程与JS引擎线程互斥
  • JS引擎线程:也叫JS内核,负责解析执行JS脚本的主线程,JS引擎一直在等待任务队列中任务的到来。
  • 事件触发线程:控制事件,例如鼠标键盘等,当事件被触发时会把处理函数推进事件队列,等待JS引擎线程执行。
  • 异步http请求线程:通过XMLHttpRequest链接后,浏览器新开了一个线程,监控readyState状态变更时,会将该状态回调函数推入事件队列等待JS引擎执行。

(三)、JS引擎线程单线程的原因

由于Javascript最初作为浏览器脚本语言开发,并且Javascript需要操作Dom等浏览器的API,若多个线程同时进行Dom更新操作,则可能会出现各种问题(如竞态条件、数据不同步、复杂的锁逻辑等),因此JS引擎设计成单线程可避免这些问题。 虽然JS引擎是单线程的,但是可以通过异步编程事件循环机制实现高并发处理。

(四)、GUI渲染线程与JS引擎线程互斥

由于JavaScript可操作Dom,如果在修改元素属性的同时渲染页面(JS引擎和GUI引擎同时运行),那么渲染线程前后获得的元素不一致。 因此为了防止渲染出现不可预期的结果,浏览器设置GUI引擎与JS引擎互斥,当JS引擎执行时GUI引擎会被挂起,保存在一个队列中等待JS引擎空闲时立即被继续执行。

(五)渲染过程中遇到JS文件/script标签时?

构建DOM树时,HTML遇到了JS,那么它会暂停文档解析,将控制权移交给JS引擎,等JS引擎运行完毕,再从中断的地方恢复解析。JS会阻塞页面加载。因此要避免在首屏加载JS文件,或给script标签加defer或async属性

  • defer:渲染完再执行
  • async:下载完就执行

二、页面渲染流程

(一)基本流程

  1. 解析HTML:解析HTML构建DOM树;
  2. 解析CSS:解析CSS构建CSSOM树(样式树);
  3. 合成渲染树:将DOM和CSSOM合并成渲染树(Render Tree);
  4. 布局计算:根据渲染树结构,计算每个节点在屏幕上的大小位置等,生成布局信息(Layout布局树)。此过程可能会发生回流和重绘
  5. 分层:主线程使用复杂策略对布局树进行分层;(将来某层改变后,仅会对该层进行后续处理,提升效率)
  6. 绘制:通过GPU绘制;

(二)回流和重绘

  • 回流:重新计算layout树,回流是异步完成的,会在JS代码全部完成后统一进行计算。(页面首次渲染、浏览器窗口变化、元素的尺寸/位置/内容变化、字体大小变化、元素删减、激活伪类等DOM结构变化)
  • 重绘:可见样式的变化(颜色、背景色等)比回流消耗性能小。

(三)CSS和JS阻塞渲染

  1. JS加载会阻塞CSS的解析和渲染,并且JS加载会阻塞DOM的解析和渲染。
  2. CSS加载不会阻塞DOM的解析,但是会阻塞DOM渲染。CSS加载会对后续JS的执行造成阻塞。
  3. 因此script标签最好放底部,link(css)标签最好放头部,若头部两者同时存在,则script标签在link之上。

三、Websocket

(一)Websocket概念

Websocket是一种在单个TCP连接上进行双工通信的协议,实现客户端和服务器之间数据双向传输。浏览器与服务器只需要完成一次握手就可以创建持久性连接。本质上是一种计算机网络应用层TCP的协议,弥补http协议在持久通信能力上的不足。

(二)Websocket原理

  1. 借用HTTP协议来完成三次握手建立起TCP连接,请求中存放Websocket支持的相关信息:Upgrade:websocketconnection:Upgrade、Websocket-Key、Websocket-Protocol(区分URL)、Websocket-Version等;
  2. 服务器收到客户端握手请求后,同样采用Http协议回馈数据;
  3. 最后客户端收到建立连接成功消息后,开始接触TCP传输信道进行全双工通信。

二、回收机制

1、浏览器回收机制

标记清除和引用计数两种;标记清除:进入执行->标记“进入环境”->离开->标记“离开环境”随后回收。

2、V8垃圾回收机制

  • (1)新生代垃圾回收:创建对象首先被分配到From空间,主线任务结束后进入回收过程,标记活跃的对象复制到To空间,同时进行压缩整理,接着清除From空间中所有对象,最后将两空间角色互换。
  • (2)老生代垃圾回收:采用标记-清除(mark-sweep)和标记-整理(mark-compact):从根节点出发查找进行标记,mark-sweep清理以后,内存可能会不连续,mark-compact会把活动对象移动至堆内存的一端。
  • (3)对象晋升:新生代中经过多次复制依旧存活,则会转移到老生代。对象晋升的条件:经历Scavenge算法或To空间内存超过25%。

三、内存泄漏

1、内存泄漏分析

(1)Heap snapshot打印快照,堆快照文件显示页面的js对象和相关dom节点之间的内存分配; (2)Allocation instrumentation on timeline在时间轴上记录内存随时间变化; (3)Allocation sampling-内存信息采样。

2、内存泄漏原因

  • (1)意外的全局变量
  • (2)被遗忘的定时器或回调函数
  • (3)脱离DOM的元素引用,dom容器删除后变量未置为null
  • (4)持续绑定的事件addEventListener
  • (5)EventBus的事件未解绑
  • (6)闭包引起的内存泄漏,比如事件处理回调,导致DOM对象和脚本中对象双向引用。
  • (7)第三方库创建后未调用正确的销毁函数
  • (8)单页应用,页面路由切换后内存未释放
  • (9)控制台打印

3、解决内存泄漏

  • (1)变量先申明后使用;
  • (2)及时clear定时器;
  • (3)若在勾子函数中绑定了DOM事件,应在销毁前remove;
  • (4)若在钩子函数中使用了EventBus.on,应在beforeDestory中off掉。
  • (5)若使用了第三方库应作对应销毁处理
  • (6)使用keep-alive时,要在deactivated进行清理。

四、跨域

  1. 跨域原因:同源策略限制,同源包括:协议、域名和端口号,同源策略为了防止不同域之间的内容进行交互。
  2. 跨域常用解决方案:
  • (1)JSONP:通过动态插入标签来请求不同源的数据,JSONP只支持GET请求。
  • (2)CORS(跨域资源共享):一种W3C规范,Access-Control-Allow-Origin来允许跨域请求。
  • (3)代理服务器:通过搭建代理服务器转发前端请求,前端向代理服务器发请求,再由代理服务器去请求不同源的资源。
  • (4)window.postMessage:H5的新API,允许来自不同源的脚本进行通信。通过监听window的message事件接收其他窗口发来的消息。

五、web安全攻击方式及防御方式

1、XSS(跨站脚本攻击)

通过恶意脚本获取敏感信息或劫持用户对话,盗取Cookie。

  • (1)反射型XSS攻击:恶意脚本注入URL参数,钓鱼邮件、诱导点击链接。
  • (2)存储型XSS攻击(持久):恶意脚本存储到数据库中,并在用户的浏览器中执行。
  • 防御措施
  • (1)对用户输入进行验证和过滤。
  • (2)对输出到页面的内容进行转译:html实体编码转义、js字符串转义、URL编码转义。
  • (3)使用HTTPOnly Cookie:放置恶意脚本通过document.cookie获取用户Cookie
  • (4)设置CSP:通过在HTTP相应头中设置策略来告诉浏览器只信任特定的资源来源。

2、CSRF

同源策略的漏洞

  • 用户已登录目标网站,并且其浏览器中保存了有效的认证凭据(如 cookie)。
  • 攻击者通过诱导用户访问恶意网站或点击恶意链接,自动向目标网站发送请求。
  • 浏览器会自动附带用户的凭据(如 cookie),使得该请求被目标网站认为是合法用户发起的,从而执行相应操作。

防御措施

  • (1)验证来源:服务器端验证请求来源的可信度,如Referer、Origin等信息。
  • (2)使用CSRF Token:在表单中添加随机生成的Token,服务器端验证该Token的合法性。
  • (3)禁用第三方Cookie。
  • (4)对于Cookie使用SameSite属性,标记只能在同站点发送,防止跨站点自动携带Cookie。

3、中间人攻击

通过劫持网络传输的数据包,获取敏感信息。

防御措施: 使用Https协议进行数据传输,通过数字证书验证服务器身份,确保与服务器之间的通信没被篡改。 Https加密过程:

  • (1)客户端向服务器发一个HTTPs请求,包含支持的密码套件列表(加密算法、摘要、密钥交换算法)以及一个随机数。
  • (2)服务器将自己的证书发给客户端,证书中包含公钥、服务器信息、签名等。
  • (3)客户端收到证书进行验证,验证证书合法性以及签名(证书验证)
  • (4)验证通过后客户端生成随机的对称加密密钥,使用服务器证书中的公钥加密后发给服务器。
  • (5)服务器收到加密后的堆成密钥,用自己的私钥解密,得到客户端生成的堆成密钥。
  • (6)客户端和服务器使用协商好的加密算法和堆成密钥进行通信

六、浏览器兼容问题(webpack解决)

  1. 配置需要兼容的浏览器:用browserlist来配置需要兼容的浏览器。
  2. CSS兼容:给css自动添加前缀,用postcss包实现。webpack安装配置postcss-loader,并配合autoprefixer补齐CSS3前缀。
  3. JS兼容:通过babel实现将ES6语法向之前版本做转换,但类似Promise这种高级语法还需借用polyfill。webpack安装配置配置babel-loader,并配合polyfill插件

七、网络性能优化——CDN内容分发网络

CDN内容分发网络,利用靠近每位用户的服务器,更快更可靠的将音乐、视频、图片及其他文件发给用户,从而提供快速、高效、低成本的内容传输服务。

1、CDN组成

  • (1)分发服务系统:最基本的工作单元是cache设备(存储设备),主要负责将内容从源服务器推送到全网的缓存服务器中,这些缓存服务器随后为用户提供内容服务。
  • (2)负载均衡系统:为用户的服务请求进行优化的访问调度,以确定向用户提供服务的最优服务器物理位置。全局负载均衡根据用户就近原则进行调度,本地负载均衡负责内部设备的负载分配。
  • (3)运营管理系统:负责处理CDN系统的日常运营和业务管理,包括运营管理和网络管理子系统,并包含客户管理、产品管理、计费管理和统计分析等功能。

2、CDN原理流程

  • (1)内容分发:CDN服务器将网站或应用内容(HTML、CSS、JS文件、图片视频等)缓存到各地缓存服务器上。
  • (2)提供访问路由:当用户请求网站时,CDN通过智能DNS解析或HTTP重定向等机制,将用户的请求引导至就近且负载低的CDN节点上。
  • (3)缓存加速:CDN节点检查并快速响应用户请求,如果资源已缓存则不需要请求源服务器直接返回,未缓存则请求源站厚返回。
  • (4)负载均衡:CDN系统自动检测各节点的健康状况,确保流量均匀分布,避免单节点过载。

3、CDN的意义

  • (1)网站加速:通过将静态资源(图片、视频、样式)等放在CDN上,用户可就近从CDN服务器上获取资源,加快网页加载速度,提升用户体验,确保用户可流畅观看视频、音频。
  • (2)减轻服务器压力:由于CDN缓存大量静态资源,减少了回源请求,从而减轻源服务器的负载。针对高并发网页有极大的优化意义
  • (3)跨地域网络优化:对于跨地区的企业、服务提供商等,CDN能够优化全球网络传输,提高数据传输效率,降低网络延迟,改善传输质量。
  • (4)支持直播服务。

八、渲染模式

1、CSR(客户端渲染)

(1)工作原理:服务器将初始HTML迅速发给浏览器,再由JS异步加载数据并渲染页面。使页面能更快速地呈现,并在后续交互中动态更新

(2)优点:

  • 减轻服务器压力:服务器主要负责提供数据,不需要负担HTML渲染工作,因此在高并发情况下,服务器压力相对较小。
  • 更简单的前端逻辑:前端代码更为简单,服务器只需提供数据,不用担心HTML渲染

(3)缺点:

  • 首屏加载慢:由于初始加载只有简单的HTML内容,页面的完整渲染需要等到JS加载和执行完毕,因此首屏加载速度慢。
  • SEO不友好:初始HTML内容简单,动态内容需要通过JS加载,使搜索引擎难以获取完整的页面信息,影响SEO。

2、SSR(服务端渲染+水合)

(1)工作原理:Web服务器预先渲染好课程先的初始页面,浏览器请求页面的初始状态,收到厚渲染响应的页面并加载对应JS和样式表,然后对页面进行水合,此后JS在浏览器中执行,接管页面的交互和动态内容的更新。

(2)优点:

  • 首屏加载快:用户访问页面时能快速获取到初步渲染的内容,提高首屏加载速度。
  • SEO友好:由于搜索引擎能够直接获取到完整的HTML内容,因此对搜索引擎的友好度较高。
  • 更好的前端性能:SSR能减轻客户端的工作负担,客户端只需要进行简单渲染即可。

(3)缺点:

  • 服务器压力大:服务器需要负责渲染HTML内容,因此在高并发情况下,服务器面临压力较大。
  • 较复杂的前端逻辑:由于首次加载时为服务端渲染,因此前端逻辑可能较复杂,需要更多的服务端和客户端协同工作。