浏览器端面试四大问:浏览器的缓存,浏览器渲染原理,存储,跨域(个人笔记)
浏览器的缓存,浏览器渲染原理,存储,跨域
浏览器的缓存
浏览器的缓存,缓存的一般是一些内存比较小的静态的资源。缓存的主要位置是:
- Service Work
- Memory Cache:浏览器自带,内存较小,速度较快
- Disk Cache:存在本地,内存较大,加载速度较慢
- Push Cache
缓存策略:
主要分为两种强缓存和协商缓存
强缓存
强缓存是利用 Expires 或 cache control 这两个 http response header 实现;
强缓存是浏览器现在缓存中查找是否有该资源。命中时状态码为 200
**Expires:**是老浏览器使用的,是一串带有固定时间的字符。他表示的是这个资源缓存的过期时间。
它的工作原理是:
在浏览器第一次向服务器请求资源时,服务器会给浏览器返回资源和带有 response 的 Expires 的 header。服务器会把资源存在缓存中,当浏览器第二次请求时,它会在缓存中查找是否有这个资源,如果有的话,就把 exprice 和当前的时间作比较,如果时间过了则未命中去服务器请求资源。命中则从缓存中获取资源。
它的缺点:因为它是和本地时间作比较的,当你的本地时间不准时它很有可能有误差。所以为了解决这个问题就有了 cache control;
cache control: 是一串数字,以秒为单位,代表的是过多久时间过期。
它的工作原理是:
在浏览器第一次向服务器请求资源时,服务器会给浏览器返回资源和带有 response 的 cache control 的 header。服务器会把资源存在缓存中,当浏览器第二次请求时,它会在缓存中查找是否有这个资源,如果有的话,他会根据第一次请求的时间和 cache control 的时间计算一个资源过期时间,然后拿过期时间和当前请求的时间做对比,如果时间过了则未命中去服务器请求资源。命中则从缓存中获取资源。
它的性能比 Expires 更好一点,两个可以同时启动也可以只启用一个,如果都启用的话优先 cache control。
协商缓存
协商缓存主要是利用 http respense header 中的 ETge 和 Lastmodified 这两组。
协商缓存是在强缓存未命中的情况下,服务器向浏览器发送请求验证协商缓存是否命中。命中时状态码为 304。
Lastmodified: 是一串时间字符:代表的是缓存过期的时间
浏览器在第一次向服务器端请求资源时候,服务器端会向浏览器端返回资源和 response 的 header 上 lastmodified,这个 lastmodified 表示这个资源在服务器上的最后修改时间。再次向服务端请求资源时,服务端就会返回加上 If-Modified-Since 的 header,他表示的就是上一次请求时返回的 Last-Modified 的值。根据浏览器传过来 If-Modified-Since 和资源在服务器上的最后修改时间判断资源是否有变化,来判断是否命中。命中就返回 304 状态码,同时让浏览器去缓存中拿资源。未命中则就从服务端获取资源。
缺点:当你在浏览器端打开缓存文件时,就是你没有修改文件,浏览器也会判定你修改了资源,这样就会导致协商缓存的判断有误。为了解决这个问题,于是又有了 ETag 来判断协商缓存。
ETag; 是一段特殊的字符,唯一标识的字符串。
浏览器在第一次向服务器端请求资源时候,服务器端会向浏览器端返回资源和 response 的 header 上 ETag,一段唯一辨识的字符串,再次请求时也会返回一段 ETag,如果资源修改则返回的 ETag 是不一样的,所以通过判断两者是否相同,来判断资源是否修改,来判断是否命中缓存。
一般浏览器两种协商缓存的方式都会存在,防止 Lastmodified 的不稳定。
一般协商缓存都是配合着强缓存,如果没有强缓存,协商缓存就没有什么意义。协商缓存主要是为了帮助强缓存判断资源是否更新。
浏览器渲染原理
浏览器的渲染主要是 5 个阶段;
-
浏览器读取 html 文件生成 DOM 树,他先将代码生成指令,这个过程叫做指令化,然后再指令化后,将这些指令生成 node 节点,这些 node 节点之间的关系就作为脐带,将这些节点串成一棵 DOM 树。
-
浏览器读取 css 文件,将 css 代码生成 cssom。
-
合并 DOM 树和 cssom,生成渲染树。这个过程浏览器递归每个 node 节点,并给节点一个样式规则并使用。这一步需要注意,display:none 并不会出现再渲染树中,它会出现在第一步的 DOM 树中,里面还会出现注释和 script 标签。
-
渲染树布局 它会帮我们输出布置每个节点的出现的位置和大小等,就再浏览器端的位置,布置成一个一个的盒模型
-
渲染树绘制 它会将那些盒模型绘制上它的样式,色彩图片等等
考点 1: 为什么操作 DOM 慢?
-
因为操作 DOM 用到了两条线程,js 的引擎线程和渲染线程,js 是单线程执行的,所以两天线程需要通信才能一起执行,这样会大大增加性能消耗。
-
操作 DOM 会引起回流和重绘。
考点 2:同时加入 10 万条 dom,如何实现不卡顿。
- 分页处理。
- 使用 requestAnimationFrame 来处理,每过 16.6 秒循环插入 dom.
- 使用虚拟 DOM,只加载可视区域的 dom,加载更多的时候,用虚拟 DOM 去替换
考点 3:优化,减少阻塞
- 减少选择器的使用,这样能减少 DOM 遍历的层级,降低渲染的文件的大小
- script 标签会阻塞渲染进程,所以我们的 script 代码应该写在 html 文件的下面。
- 没有任何依赖的 js 文件我们可以加上 asyac 属性,这样就不会影响渲染的进度。
考点 4:重绘和回流
- 重绘不改变布局,只改变一些颜色什么的
- 回流会改变布局。
- 回流一定会引发重绘。
浏览器的存储
Cookie, LocalStorage, sessionStorage, IndexedDB
Cookie
浏览器是无状态的,他无法记住浏览器上一步做的是什么,所以很多功能无法实现,比如购物车,所以浏览器创建 cookie 来使用,用于保存用户的状态,在购物东西时 cookie 就好像一辆购物车,用来保存用户选购的商品信息,它在浏览器和服务器之间来回传输信息。
Cookie 指某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密)。 cookie 是服务端生成,客户端进行维护和存储。通过保存用户的信息,来保存登录状态,登录还刷新还能回到原来的状态。可以保存一段时间。
缺点:
- 内存较小一般就几 k 大小,所以只能保存用户信息不能保存大文件内容。
- cookie 过多可能会带来过的性能消耗。
- cookie 还存在一定的安全性。
LocalStorage
- 内存较大有 5M 左右
- 除非被清除否则永久保存
- 接口容易封装
- 仅在浏览器中保存,不参与通信
sessionStorage
- 内存较大有 5M 左右
- 关闭页面就消失
- 接口容易封装
- 仅在浏览器中保存,不参与通信
IndexedDB
- 内存无线
- 永久保存
跨域
数据的请求都要遵循同源策略,既需要同域名,同端口,同协议。所以违反了这个规则则就算跨域了。
解决跨域的四个方法:
- From 表单能够帮我们跨域请求信息。疯狂发送请求
- jsonp 利用的没有跨域限制请求
- cors 后端设置允许跨域,或者搞个白名单,允许那些能跨域请求
- nginx 代理
最后:有时间再整理跨域和存储。
评论区