浏览器原理学习笔记

11 篇文章 0 订阅

浏览器原理

进程:启动程序时,操作系统会创建一块内存供程序使用,这就是进程。
线程:进程内部内存分配最小单元,进程包含多个线程,提高并行处理效率。

  1. 进程之间完全隔离,某个进程崩溃不会影响其他进程。
  2. 进程中并发多个线程,负责执行不同任务。
  3. 线程共享进程中的数据,互相可以直接通信,任意一个线程出错,进程就会崩溃。
  4. 进程间通信需要特殊方式。

进程间通信(IPC)方式:

  • 管道通信:就是操作系统在内核中开辟一段缓冲区,进程1可以将需要交互的数据拷贝到这个缓冲区里,进程2就可以读取了
  • 消息队列通信:消息队列就是用户可以添加和读取消息的列表,消息队列里提供了一种从一个进程向另一个进程发送数据块的方法,不过和管道通信一样每个数据块有最大长度限制
  • 共享内存通信:就是映射一段能被其他进程访问的内存,由一个进程创建,但多个进程都可以访问,共享进程是最快的IPC方式
  • 信号量通信:比如信号量初始值是1,进程1来访问一块内存的时候,就把信号量设为0,然后进程2也来访问的时候看到信号量为0,就知道有其他进程在访问了,就不访问了
  • socket:其他的都是同一台主机之间的进程通信,而在不同主机的进程通信就要用到socket的通信方式了,比如发起http请求,服务器返回数据

早起浏览器是单进程的,网络,JS运行,渲染等都在一个进程中,这会导致:

  • 不稳定,标签页卡死,可能导致整个浏览器崩溃。
  • 不安全,由于同一进程内的线程可以共享数据,JS线程就可以随意获取浏览器数据,可能导致恶意攻击。
  • 性能差,一个进程需要负责太多事情,会导致运行效率问题

现代V8浏览器打开一个页面至少包括:浏览器进程、渲染进程、GPU进程、网络进程。如果浏览器使用了插件,还会包含插件进程。

  • 浏览器进程: 负责控制浏览器除标签页外的界面,包括地址栏、书签、前进后退按钮等,以及负责与其他进程的协调工作,同时提供存储功能
  • GPU进程:负责整个浏览器界面的渲染。Chrome刚开始发布的时候是没有GPU进程的,而使用GPU的初衷是为了实现3D CSS效果,只是后面网页、Chrome的UI界面都用GPU来绘制,这使GPU成为浏览器普遍的需求,最后Chrome在多进程架构上也引入了GPU进程
  • 网络进程:负责发起和接受网络请求,以前是作为模块运行在浏览器进程里面的,后面才独立出来,成为一个单独的进程
  • 插件进程:主要是负责插件的运行,因为插件可能崩溃,所以需要通过插件进程来隔离,以保证插件崩溃也不会对浏览器和页面造成影响
  • 渲染进程:负责控制显示tab标签页内的所有内容,核心任务是将HTML、CSS、JS转为用户可以与之交互的网页,排版引擎Blink和JS引擎V8都是运行在该进程中,默认情况下Chrome会为每个Tab标签页创建一个渲染进程

在渲染进程中又包含多个线程:

  • GUI渲染线程:负责渲染页面,解析html和CSS、构建DOM树、CSSOM树、渲染树、和绘制页面,重绘重排也是在该线程执行
  • JS引擎线程:一个tab页中只有一个JS引擎线程(单线程),负责解析和执行JS。它GUI渲染进程不能同时执行,只能一个一个来,如果JS执行过长就会导致阻塞掉帧
  • 计时器线程:指setInterval和setTimeout,因为JS引擎是单线程的,所以如果处于阻塞状态,那么计时器就会不准了,所以需要单独的线程来负责计时器工作
  • 异步http请求线程: XMLHttpRequest连接后浏览器开的一个线程,比如请求有回调函数,异步线程就会将回调函数加入事件队列,等待JS引擎空闲执行
  • 事件触发线程:主要用来控制事件循环,比如JS执行遇到计时器,AJAX异步请求等,就会将对应任务添加到事件触发线程中,在对应事件符合触发条件触发时,就把事件添加到待处理队列的队尾,等JS引擎处理。
  • 合成线程:负责生成视口附近的图块,为光栅化生成位图做准备。

用户在输入URL到页面展示发生了什么

在这里插入图片描述

  1. 浏览器主进程检测用户输入内容,如果是域名,则会补齐协议。如果是不符合域名格式,则会使用浏览器默认搜索引擎进行搜索。页面跳转之前,还会在当前页面调用一次beforeunload 事件,数据清理、确认离开。
  2. 浏览器主进程通过进程间通信 IPC 来将url请求交给网络进程。由网络进程发起请求。
    • 网络进程会查找该请求是否在本地有缓存,如果有则使用缓存,如果没有则准备发送网络请求。(这里缓存指强缓存,如果强缓存过期,会进入协商缓存,仍会发送请求)
    • 请求首先要去 DNS(域名和IP地址映射服务) 上获取IP地址,建立TCP连接,构建请求信息并添加cookie到请求头中,然后发送HTTP请求
  3. 服务器接收到请求后,将响应数据发送回网络进程。
  4. 网络进程解析响应头中的字段(跨域拦截)并传递给主进程。如果状态码是301或302,表明地址需要重定向,此时读取响应头中 Location 字段中的重定向URL,然后重新发起一遍流程。
  5. 状态码为200:可以正常处理响应数据。此时浏览器主进程根据 Content-Type 字段的类型来判断如何处理响应数据。如果是 text/html 格式,则准备渲染进程。
  6. 准备渲染进程:并不是每个页面都会分配一个新的渲染进程,如果两个页面是同一根域名下,就可能使用同一渲染进程。在这里还会进行一次判断。
  7. 提交文档:
    1. 浏览器进程接受到网络进程的响应头数据,向渲染进程发送『提交文档』消息;
    2. 渲染进程收到『提交文档』消息后,与网络进程建立传输数据『管道』,传递html文本数据。
    3. 传输完成后,渲染进程返回『确认提交』消息给浏览器进程;
    4. 浏览器接受『确认提交』消息后,移除旧文档、更新界面、地址栏,导航历史状态等,浏览器进入渲染阶段。
  8. 渲染阶段
    1. 将 HTML 文本转化为 DOM 树结构(边接收html文本数据,边解析生成DOM,与文档确认提交消息发送没有明确先后) 。
    2. 将 CSS 文本转化为 styleSheets。
    3. 根据 CSS 的继承和层叠规则,计算每个DOM节点的样式
    4. 布局:构建一棵只包含可见元素布局树,计算每个元素的几何位置,并保存在布局树中。
    5. 分层
    6. 图层绘制
    7. 栅格化,渲染进程中的合成线程将图层划分为图块,并选择视口附近的图块,通过栅格化(借助GPU)转换为位图。生成的位图被保存在 GPU 内存中。
    8. 合成:栅格化完成后,合成线程会生成 DrawQuad 命令,提交给浏览器进程,并显示到屏幕上。
      在这里插入图片描述

重排,重绘,合成

  • 重排:通过 js 或 css 修改元素几何位置属性,此时浏览器会触发重新布局(渲染阶段第四步),需要更新的步骤最多,性能开销最大。
  • 重绘:修改元素外观,不影响几何属性,省去了布局和分层阶段。
  • 合成:既不修改外观,也不修改几何属性,比如 CSS3 的 transform ,还可以省去图层绘制阶段。直接在非主线程上合成,效率更高。

V8执行与垃圾回收

编译型语言:在运行时会通过编译器编译出机器能识别的二进制文件。再次运行时可以直接运行二进制文件。
解释型语言:每次运行都需要通过解释器对代码进行动态解释执行。
JS是解释型语言。

V8执行JS过程

在这里插入图片描述

  1. 将源代码通过词法分析语法分析转换为抽象语法树AST并生成执行上下文
  2. 解释器 Ignition 根据抽象语法树 AST 生成字节码
  3. 字节码生成后进入执行阶段, 解释器 Ignition 会将字节码逐条解释执行。在这个过程中,如果解释器发现热点代码 ,后台的编译器 TurboFan 就会将这段热点代码编译为机器码保存,再次执行时提高了效率(即时编译JIT
  • 抽象语法树AST 是一种数据结构,能够被编译器和解释器识别。Babel就是通过将ES6的AST转换为ES5的AST来实现的转译代码。
  • 词法分析 又叫做分词,将代码拆分成不可分割的最小字符串(token)
  • 语法分析 又叫做解析,将生成的字符串根据语法规则转换为AST。如果不符合规则会抛出语法错误。
  • 字节码 介于AST和机器码之间的一种代码。无法直接识别,但是占用内存较机器码更少。
  • 热点代码 执行多次的代码
  • 及时编译JIT 指使用字节码配合解释器和编译器来优化提效的方案

V8垃圾回收

对于保存在栈中的数据,JS通过一个指针ESP来判断当前执行位置,当函数执行完毕以后,该指针也会移动到栈中的下一个执行上下文,之前函数的上下文环境也就无效了,如果有新的函数上下文入栈,会自动替换掉。

在这里插入图片描述
对于保存在堆中的数据,需要JS的垃圾回收器了。V8将堆分为新生代老生代两个区域,并分别通过副垃圾回收器主垃圾回收器分别处理。处理的机制都是先标记活动对象与非活动对象,回收非活动对象内存,最后进行内存整理(主垃圾回收器)。

新生代:存放生存时间短,且较小的对象。使用 Scavenge 算法,将新生代空间对半分,快写满一半的时候,进行一次清理,将标记的活动对象复制到另一半,再顺序排列,然后两半翻转。

在这里插入图片描述

老生代: 存放生存时间相对长,且较大的对象。使用标记 - 清除(Mark-Sweep)算法,递归遍历调用栈,能够到达的对象标记为活动对象,无法到达的则为垃圾数据。清除之后还需要通过标记 - 整理(Mark-Compact)算法来进行内存整理。

同源策略

同源:域名、端口、协议相同。

同源策略限制:

DOM层面:限制了来自不同源的 JavaScript 脚本对当前 DOM 对象读和写的操作。
可以通过 window.postMessage 来实现非同源页面DOM通信,原理是通过监听消息的方式,本质上还是操作自身DOM。

数据层面:限制了不同源的站点读取当前站点的 Cookie、IndexDB、LocalStorage 等数据。

网络层面:限制 ajax 请求非同源网站数据。

解决跨域的方法

务器端代理,让同源策略对代理服务器生效,再由代理服务器转发请求,绕过跨域限制。
JSONP(JSON with Padding):通过动态创建script标签,利用callback函数的方式来实现跨域请求。
CORS(Cross-Origin Resource Sharing):在服务端设置响应头部信息,允许指定域的访问,从而实现跨域请求。
WebSocket协议:使用WebSocket协议进行跨域通信,WebSocket不受同源策略限制。
跨文档消息传输(Cross-document messaging):在不同域的页面间传递消息,可以通过window.postMessage()方法实现跨域通信

XSS攻击

跨站脚本攻击。指黑客向HTML文件或是DOM中注入恶意脚本来进行攻击。常见攻击手段有窃取 cookie 信息、监听用户行为(键盘操作)、修改DOM伪造表单窃取密码、生成广告等。

根据脚本的注入方式可以分为存储型、反射型和DOM型,前两种都属于服务端攻击,DOM型属于前端攻击。

如何防止

  1. 对脚本进行过滤或转码。
  2. 利用内容安全策略( CSP ) ,设置响应头或是mate标签
  3. 重要cookie使用 HttpOnly 属性,只能在HTTP请求中使用,无法通过脚本获取。

CSRF攻击

CSRF 跨站请求伪造,黑客获取了用户的登录状态,并通过第三方的站点伪造用户请求来进行攻击。

如何防止

  1. 通过对登录信息等关键 cookie 设置 SameSite 属性。

SameSite 可以设置三个值

  1. Strict 最严格,完全禁止第三方请求携带Cookie.
  2. Lax 相对宽松,允许第三方的GET请求或是打开连接可以携带cookie
  3. None 不限制。
  1. 在服务端验证请求来源站点,优先验证请求头中的 origin 字段,如果没有,则验证 referer 字段。
  2. 使用 CSRF Token 。在浏览器发起请求的时候,服务器会生成一个CSRF Token 字符串并返回客户端,后续在转账等敏感请求提交的时候携带上这个token。

浏览器性能优化

DOM树生成

在网络进程收到服务器发来的响应之后,会根据响应头中的 content-type 字段来判断文件类型。如果是 text/html ,此时浏览器就会选择或是创建一个渲染进程,然后建立网络进程与渲染进程的通信管道。

渲染进程内部通过 HTML解析器 来将接收到的HTML字节流转化为DOM结构,边接收边解析

具体的解析流程

  1. 将字节流通过分词器转化为一个个 token 字符串,类似JS的词法分析。
  2. HTML解析器内部维护了一个栈结构,用来存放 token。遇到起始标签会入栈,终止标签会将对应的起始标签出栈,文本标签不会压入栈中。 在解析起始标签的时候就会创建对应的DOM节点。
    在这里插入图片描述

JS阻塞DOM执行

如果 HTML 中通过 script 标签内嵌有 JS 脚本,就会阻止DOM的解析,先下载并执行JS脚本,因为脚本中可能有修改DOM节点的操作。

如果确认脚本不会修改DOM,可以使用 async or defer 标记来异步加载

async:异步加载脚本,加载完成之后立即执行,无法保证顺序
defer:延迟加载脚本,在DOMContentLoaded事件之前执行。(DOM解析完毕就执行)

JS执行依赖CSS解析

由于JS内部可能有修改CSS样式的代码,这就要求在JS脚本执行前,CSS文件必须下载完成并解析成JS能够识别并操作的CSSOM结构。

在加载外部JS或是CSS资源并解析的过程,页面可能会解析白屏。缩短白屏时长有如下方法:

  • 通过内联JS和CSS来减少或移除这两种文件的下载。
  • 如果不能替换,可以通过打包工具,或拆包等手段压缩文件体积。
  • 通过媒体查询属性,区分不同场景的CSS

在这里插入图片描述

交互阶段

交互阶段,主要是从页面加载完成到用户交互的整合过程,影响到这个阶段的主要因素是 JavaScript 脚本。

对于一些执行事件过长的脚本,可能会占用

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值