浏览器

浏览器缓存

z3ZYGj.md.png

强缓存

早期HTTP1.0

通过Expires字段,存在于浏览器返回的响应头中,告诉浏览器这个过程是可以直接从浏览器获取数据,无需再次请求。

1
Expires: Wed, 22 Nov 2019 08:41:00 GMT 

但是由于服务器和浏览器时间可能并不一致,因此在HTTP1.1中这种操作被废弃了。

Cache-Control

区别于Expires的具体的过期时间,前者采用了过期时长来控制。

1
Cache-Control:max-age=3600

还有其他参数

  • private只有浏览器进行缓存
  • no-cache跳过强缓存,直接进入协商缓存
  • no-store不进行缓存
  • s-maxage针对代理服务器的缓存时间

协商缓存

当强缓存失效后,浏览器在请求头中携带相应的缓存tag来向服务器发请求,由服务器根据这个tag,来决定是否使用缓存。

缓存tag:

  • Last-Modified最后修改时间

    服务器在第一次响应后会在响应头添加这个字段,也就是服务器的最后修改时间,浏览器第二次请求会加上浏览器传过来的最后修改时间,若服务器端修改时间改变,则直接更新,返回新的资源。否则返回304,告诉浏览器直接使用缓存

  • ETag文件唯一标识

    ETag是服务器根据当前文件内容给浏览器添加的唯一标识,第一次请求时,浏览器会将ETag直接放在响应头发送给浏览器,浏览器在下次请求后会将这个值作为If-None-Match

    这个字段的内容,将其发送给服务器,服务器再进行对比,并决定浏览器是否使用缓存。

两者对比:

从精准度来将,ETag显然更高,而从性能来看,Last-Modifie显然更方便。

缓存存放的位置

按照优先级高低排列依次是:

  • Service Worker

    借鉴了webworker的思路,让js运行在主线程之外,但是脱离了浏览器窗体,不能操纵DOM

  • Memory Cache

    效率快,但存活时间短

  • Disk Cache

    效率慢,但存活时间长

  • Push Cache

    在HTTP2.0才更多的使用

总结:

z3ZBZT.md.png

浏览器本地存储

主要分为:

  • Cookie

    Cookie最早设计出来仅仅是为了弥补HTTP状态管理上的不足

    本质上就是在浏览器存储一个很小的文本文件(4KB)

    但是Cookie有很多致命的缺陷:

    • 容量缺陷(4K)
    • 性能缺陷(Cookie紧跟域名,尽管该域名某些地址下不需要这些Cookie,请求都会携带上完整的Cookie,这个可以通过设置Cookie来配置)
    • 安全缺陷(由于Cookie是以纯文本的形式在浏览器和服务器之间传递,因此很容易被非法劫持篡改,在Cookie有效期内重新发送给服务器,这是相当危险的。而且在HttpOnly为false的情况下,可以用js脚本直接获取Cookie)
  • webStorage

    localStorage与Cookie相似,也会针对一个域名存储数据,但是与Cookie区别很大

    • 容量上线是5M,而且是持久存储
    • 只存在客户端,默认不参与服务端通信,避免了Cookie带来的性能问题和安全问题
    • 接口封装

    sessionStorage页面关闭就会消失

    • 可以对表单信息进行维护
    • 可以用来存储本次浏览记录,例如微博就是
  • IndexedDB

    运行在浏览器的一个非关系型数据库,理论上它的容量没有上线

    • 键值对存储
    • 异步操作
    • 受同源策略影响

输入浏览器到页面呈现发生了什么?

网络角度

(1)构建请求

1
2
// 浏览器会构建请求行
GET / HTTP/1.1

(2)查找强缓存

先查找强缓存,若命中则直接使用,否则进入下一步

(3)DNS解析

由于输入的是域名,而数据包是通过IP地址传给对方的。因此我们需要得到域名对应的IP地址。也就是域名系统与IP的一个映射。

浏览器有DNS数据缓存的功能,即一个域名解析过,下次直接走缓存,不再需要DNS解析

(4)建立TCP连接

Chrome在同一域名下要求最多只能有6个TCP连接,超过的话剩下的请求就得等待

建立TCP连接需要经历下面三个阶段

  1. 三次握手建立客户端与服务器之间的连接
  2. 进行数据传输(接收方在接收到数据之后必须向发送方进行确认,如果发送方没接收到这个消息,则判断数据包丢失)
  3. 四次挥手断开连接

(5)发送HTTP请求

请求行+请求头+请求体

总结

z3ZRQ1.md.png

解析算法

完成了网络请求个响应,如果响应头中Content-Type的值是text/html,那么接下来的就是浏览器的解析和渲染工作了。

  • 构建DOM树

    DOM树本质上是以document为根节点的多叉树

    HTML文法是上下文有关文法

    解析算法

    • 标记化
    • 建树
  • 样式计算

  • 生成布局树(Layout Tree)
    z3Z5dO.png

渲染过程

DOM树布局树(layout tree)创建之后,浏览器还会创建图层树(layer tree)

一般情况下,节点的图层默认属于父亲节点的图层(这些图层也称为合成层),那么什么时候节点会提升到单独的图层(合成层)呢?
z3ZIoD.png

  • 显示合成,如何产生合成层(形成单独的一层)

    z3e9YQ.png

  • 隐式合成,如何被动的形成合成层

    当层级比较底的节点被提升为单独的图层之后,那么所有层级比他高的节点都会成为一个单独的图层。
    层爆炸原理当一个z-index比较低的元素被提升为单独图层之后,层叠在他上面的元素统统会被提升为单独的图层,可能会增加上千个图层,大大增加内存压力!但是现在浏览器优化做的很好,已经很少存在层爆炸现象了!(层压缩)

  • 合成层的优缺点

    优点:

    • 合成层的位图会交给GPU合成,比CPU快,减轻CPU负担
    • 需要repaint时,仅仅重绘本身,不会影响到其他图层
    • transform 和 opacity 才不会触发 repaint,如果不是合成层,则其依然会触发 repaint。

    缺点:

    • 绘制的图层必须传输到 GPU,这些层的数量和大小达到一定量级后,可能会导致传输非常慢,进而导致一些低端和中端设备上出现闪烁;
    • 隐式合成容易产生过量的合成层,每个合成层都占用额外的内存,而内存是移动设备上的宝贵资源,过多使用内存可能会导致浏览器崩溃,让性能优化适得其反。

重绘、回流、合成

重绘

触发条件

当DOM的修改导致样式的变化,并且没有影响几何属性的时候,会导致重绘

重绘过程

z3enkF.png
重绘不一定导致回流,但回流一定发生重绘

回流

触发条件

当对DOM结构的修改引发的DOM集合尺寸变化的时候,会发生回流

  • 几何属性:width、height、padding、margin、left、top、border等
  • DOM节点发生增删或移动
  • 读写offset、scroll、client族属性时,浏览器为了获取这些值,会进行回流操作
  • 调用window.getComputedStyle方法

回流过程

z3euY4.png

合成

有一种情况是直接合成,比如利用CSS3的transform、opacity、filter这些属性就可以实现合成的效果,也就是GPU加速。

在合成的情况下,会直接跳过布局和绘制的过程,直接进入非主线程处理的部分,即交给合成线程处理。

GPU善于进行图像处理

实践意义

  • 避免频繁修改style,而是采用修改class的方式
  • 使用createDocumentFragment进行批量的DOM操作
  • 对于resize、sscroll等进行防抖节流处理
  • 添加will-change:transform, 让渲染引擎为其单独实现一个图层

浏览器安全

XSS跨站脚本攻击(Cross Site Scripting)

指在浏览器中执行恶意脚本,从而拿到用户的信息并进行操作。浏览器没有对恶意代码进行过滤,使其在用户浏览器运行,从而:

  • 窃取Cookie
  • 监听用户行为,比如输入账号密码之后直接发送到黑客服务器
  • 修改DOM伪造登录表单
  • 在页面中生成悬浮广告

XSS也分为下面三种方式:

  • 1. 存储型

    z3eYTO.png

  • 2. 反射型

    z3eafH.png

  • 3. 文档型

    z3eafH.png

防范措施(一个信念,两个利用):

  • 永远不要相信任何用户输入
  • 利用Cookie的HttpOnly进制JS脚本获取Cookie
  • 利用CSP规定浏览器只能访问特定资源

CSRF跨站请求伪造(Cross-site request forgery)

  • 自动发起GET请求

    z3eB6I.png

  • 模拟用户自动发送post

  • 诱导点击发送GET请求

解决办法:

  • 利用Cookie sameSite属性,对请求的Cookie携带进行限制
  • 验证来源站点,通过请求头里面的Origin Referer
  • CSRF Token , 例如Python Django框架,在请求的时候向服务器发送指定字符串,当再次发送请求时,客户端携带指定字符串,服务器经验证通过后,才命中请求。

中间人攻击

HTTPS为什么让数据传输更安全

由于HTTP明文传输,可能被截获、伪造请求,不会验证报文完整性

z3eh1s.png

z3eon0.png

HTTPS的优点:

  • 加密
  • 完整性校验
  • 身份认证

什么是TLS/SSL?

TLS(Transport Layer Security)是 SSL(Secure Socket Layer)的后续版本,它们是用于在互联网两台计算机之间用于身份验证加密的一种协议。

TLS使用了对称加密和非对称加密两种

对称加密,一个密钥,如果密钥泄露,就完蛋了

非对称加密,一个公钥,一个私钥,即使公钥泄露,私钥依然保存在自己手中,没完蛋,但是是单向的,我传你,你不能传我

z3eqNF.png

浏览器组成

  • 浏览器主进程
  • GPU进程
  • 网络进程
  • 多个渲染进程
  • 多个插件进程

浏览器事件循环机制

执行栈

每一个函数在运行的时候都会生成新的执行上下文,执行上下文回包含当前函数的参数,局部变量信息,正在执行的上下文始终处于栈的顶部

任务队列

优化首屏加载时间

计算方式:performance.timing.domComplete - performance.timing.navigationStart

  • 使用路由懒加载,只有在跳转到该路由时才加载组件
  • 最好使用CDN的方式引入
  • 采用HTTP缓存
  • 按需加载组件
  • 图片资源压缩
  • gzip格式压缩