前端须知-浏览器

180 阅读8分钟

浏览器相关知识

前端开发而言,浏览器就是我们所需要了解的宿主环境,不管是pc端移动端,我们的页面都是允许再浏览器当中。所以了解浏览器的知识很大程度能够理解网站运行的原理,并能高效的定位并解决问题。

从单进程到多进程的浏览器

为什么现在需要的是多线程浏览器?由于网站刚发展时都是简单的文字表格信息,通过单进程浏览器也能够很好的预览展示。随着网站的多元化丰富性,单进程已不能够满足。

当所有tabs页放在一个进程时,就会出现访问速度,浏览器健壮性,安全性等问题。若是单线程,只要有一个tab页面出错就会导致真个浏览器锁死,比如一个flash插件出错,就导致浏览器锁死。再多进程浏览器中就不会,flash插件出错只影响插件进程,浏览器进程,渲染进程,网络进程等等都还能够正常使用。

浏览器包括哪些进程呢?

  • 浏览器进程:主要处理浏览器界面上的任务,比如用户输入,前进后退按钮,打开标签页,存储功能等等。
  • 渲染进程:浏览器内核,主要处理html/css/js解析运行等等
  • 网络进程:处理网络请求任务
  • GPU进程: 起初设计为了3D渲染,后随着发展,ui界面都由GPU绘制
  • 插件进程: 管理第三方插件

什么是线程?

线程是进程的最小单位,一个进程可包括多个线程。比如渲染进程中就包括一下线程: 注意:GUI渲染线程和js引擎线程是互斥的,当js引擎执行是GUI线程会被挂起(相当于冻结),GUI更新会被报错在一个队列中等到js引擎空闲时立即被执行

  • GUI渲染线程:解析生成DOM&CSSOM树,计算样式生成layout树等等
  • JS引擎线程:js引擎线程负责解析JavaScript脚步,运行代码
  • 定时器触发线程:处理定时器任务
  • 事件触发线程:用来控制事件循环
  • 网络请求线程:处理网络请求

浏览器缓存

缓存是提高新能的重要一步,浏览器缓存分为两种:

  1. 强缓存
  2. 协商缓存 还有一个关键的知识点就是缓存的位置

详情见浏览器缓存

浏览器本地存储

主要分为:Cookie, WebStorage, IndexDB. 其中webStorage 分为localStorage和sessionStorage。

详情见浏览器本地存储

v8垃圾回收机制

v8垃圾回收机制,首先需要明白,浏览器数据的存储是怎样的需要理解JavaScript的内存机制。 这里有两个概念:

  • 栈内存
  • 堆内存

基础数据类型是通过执行上下文的形式存储在栈内存中,引用类型数据是存在堆内存中,注意的是栈内存中存储的是引用类型的地址。

栈内存的回收机制

栈内存有个ESP指针来指向目前栈的栈顶位置,当栈顶执行上下文执行完成,ESP指针下移,此时原本栈顶的数据就被删除了(因为访问不到了,若再有执行上下文入栈,会占用其位置将其覆盖掉)

堆内存的回收机制

堆内存区域分为两部分:

  • 新生代:存放新创建的数据 --- 副垃圾回收器
  • 老生代:存放旧引用类型数据 --- 主垃圾回收器

老生代容量大大于新生代。

新生代

新生代去分为两个区域:

  • 对象区域
  • 空闲区域
  1. 所有新创建对象都放在对象区域,空闲区域不放置数据。
  2. 当对象区域满之后,触发一次垃圾回收,将存活对象,放在空闲区域。当处理完成后,将对象区域数据清空。
  3. 再将对象区域和空闲区域对换,将空闲区域(此时存放着整理过后的数据)转换为对象区域,对象区域则成为空闲区域。

为了处理两次之后还存活的对象,新生代有个晋升政机制,将新生代两次垃圾回收还存活的对象,转移到老生代存储。

老生代

发生晋升其实不只是这一种原因:

  • 已经经历过一次 Scavenge 回收(两次回收之后还存活)
  • 空闲区域的内存占用超过25%。(???第一次知道这个条件,需要确认一下)

老生代垃圾回收机制:

标记-清除: 首先是标记过程阶段。标记阶段就是从一组根元素开始,递归遍历这组根元素,在这个遍历过程中,能到达的元素称为活动对象,没有到达的元素就可以判断为垃圾数据。 标记-整理:这个标记过程仍然与标记-清除算法里的是一样的,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

由于js线程是单线程的,所以在执行垃圾回收的时候,会阻塞执行js代码。如果垃圾回收时间过长可能会出现停顿时间过长,性能消耗,用户体验非常不好。所以研究出了一个增量标记算法。 增量标记:为了降低老生代的垃圾回收而造成的卡顿,V8 将标记过程分为一个个的子标记过程,同时让垃圾回收标记和 JavaScript 应用逻辑交替进行,直到标记阶段完成

详见垃圾回收机制

浏览器安全(XSS,CSRF等)

XSS(跨站脚本攻击)

脚本攻击主要的是在html页面中注入了攻击脚本(scrip) xss分为几大类:

  • 存储型:攻击者将恶意脚本通过表单提交到后端并存储到数据库中,当页面加载时读取并被浏览器执行
  • 反射型:通过特定url,将脚本添加在url上,后端获取解析并拼接在html中返回给浏览器,浏览器解析执行。
  • DOM型:基于 DOM 的 XSS 攻击是不牵涉到页面 Web 服务器的。黑客通过各种手段将恶意脚本注入用户的页面中,比如通过网络劫持在页面传输过程中修改 HTML 页面的内容,这种劫持类型很多,有通过 WiFi 路由器劫持的,有通过本地恶意软件来劫持的,它们的共同点是在 Web 资源传输过程或者在用户使用页面的过程中修改 Web 页面的数据。

XSS危害:

  • 窃取cookie等用户信息
  • 监听用户行为:监听用户输入点击等行为,比如监听到用户输入银行卡号等等
  • 修改DOM:比如伪造登录界面窃取用户信息(账号密码)
  • 恶意广告弹窗

XSS防御:

  • 前端&后端对用户输入内容做过滤和转码
  • cookie设置httpOnly禁止用户通过js获取
  • 充分利用CSP:浏览器中的内容安全策略,它的核心思想就是服务器决定浏览器加载哪些资源
    • 限制加载其他域下的资源文件,这样即使黑客插入了一个 JavaScript 文件,这个JavaScript 文件也是无法被加载的;
    • 禁止向第三方域提交数据,这样用户数据也不会外泄;
    • 禁止执行内联脚本和未授权的脚本
    • 还提供了上报机制,这样可以帮助我们尽快发现有哪些 XSS 攻击,以便尽快修复问题

详见XSS

CSRF(跨站请求伪造)

指的是黑客诱导用户打开链接访问黑客的网站,然后黑客利用用户目前的登录态,跨站发起请求。

  • 自动发起get请求

    <img src="https://xxx.com/info?user=hhh&count=100">
    
  • 自动发起post请求

      <form id='hacker-form' action="https://xxx.com/info" method="POST">
          <input type="hidden" name="user" value="hhh" />
          <input type="hidden" name="count" value="100" />
      </form>
      <script>document.getElementById('hacker-form').submit();</script>
    
  • 诱导用户点击发送 GET 请求

      <a href="https://xxx/info?user=hhh&count=100" taget="_blank">点击进入修仙世界</a>
    

和 XSS 不同的是,CSRF 攻击不需要将恶意代码注入用户的页面,仅仅是利用服务器的漏洞和用户的登录状态来实施攻击。

防范:

  1. 利用Cookie的SameSite属性
  2. 验证来源站点(origin&referer)
  3. csrf token验证

详见CSRF

从输入一个url到页面展示的过程

分三个大步骤吧:

  1. 网络请求:构建URL,判断缓存,dns解析,tcp3握手4挥手,http请求等等
  2. 解析算法:解析生成DOM,CSSOM,样式计算layoutTree
  3. 渲染页面:布局,分层,图层绘制,合成,栅格化,绘制

详见输入一个url到页面展示的过程渲染流程

V8引擎是如何执行一段JavaScript代码的

  1. 将代码经过语法分析,词法分析解析成AST(抽象语法树)和执行上下文 a. 分词token(词法分析) b. 解析Parse(语法分析)
  2. 生成字节码:字节码就是介于 AST 和机器码之间的一种代码。但是与特定类型的机器码无关,字节码需要通过解释器将其转换为机器码后才能执行
  3. 执行代码

详见V8引擎执行JS代码

参考资料: 浏览器

注:个人学习记录