一、浏览器缓存
1、对浏览器缓存机制的理解?
对于缓存机制:juejin.cn/post/710800…
2、协商缓存和强缓存的区别?
强缓存与协商缓存:juejin.cn/post/710800…
3、为什么需要浏览器缓存?
4、点击刷新按钮或者按 F5、按 Ctrl+F5 (强制刷新)、地址栏回车有什么区别?
- 点击刷新按钮或者按 F5:将本地缓存过期,客户端携带 if-modified-since 或者 if-none-match,向服务器端发送请求,服务器端进行判断,如果在时间范围内,返回304,否则返回200
- 按 ctrl+F5:将本地缓存过期,并且不会携带if-none-match、if-modified-since,向服务器发送请求,服务器返回200
- 地址栏回车:按照正常的网络请求路径进行请求,会先进行判断强缓存,然后协商缓存,再进行服务器端返回内容
5、页面可见性(Page Visibility API)有哪些好处?
这个新的 API 的意义是,通过监听网页的可见性,预判网页的卸载,可以用来节省资源,减缓电能的消耗。比如,一旦用户不看网页,下面这些网页行为都是可以暂停的:
- 对服务器的轮询
- 网页动画
- 正在播放的音频或视频
详细资料可以参考:Page Visibility API 教程
二、浏览器本地存储
1、浏览器本地存储方式及使用场景?区别?前端存储方式有哪些?
都是内存存储
1. localStorage
- 存储时间:存储在浏览器内存中,不会随着页面关闭而消失,只要不进行手动清除,会一直存在
- 存储大小:大约有5MB,可以存储更多信息
- 只存在于内存中,HTTP请求不会携带
- 受制于同源策略的局限下
- 如果浏览器设置为隐私模式,无法获取到localStorage
- 不能被爬虫提取
使用场景:
- 如果网站有换肤的需求,可以将换肤的信息存储到loaclStorage中,需要换肤的时候直接读取就可以
- 用于存储一些用户的状态信息,记住用户内容;还可以用于记录用户浏览的信息
常用代码:
// 保存数据到 localStorage
localStorage.setItem('key', 'value');
// 从 localStorage 获取数据
let data = localStorage.getItem('key');
// 从 localStorage 删除保存的数据
localStorage.removeItem('key');
// 从 localStorage 删除所有保存的数据
localStorage.clear();
// 获取某个索引的Key
localStorage.key(index)
2. SessionStorage
- 存储时间:存储在浏览器内存中,只存在于此会话中,刷新页面不会删除,关闭浏览器或此次会话关闭会清除
- 存储大小:大约有5MB
- 只存在于内存中,HTTP请求不会携带
- 受制于同源策略的局限下,但是SessionStorage有一条更加严格的限制,SessionStorage只有在同一浏览器的同一窗口下才能够共享,也就是只在当前会话中共享
- 不能被爬虫提取
使用场景:
- 可以用于游客信息的记录,或者一些临时浏览记录,关闭后信息也消失
常用代码:
// 保存数据到 sessionStorage
sessionStorage.setItem('key', 'value');
// 从 sessionStorage 获取数据
let data = sessionStorage.getItem('key');
// 从 sessionStorage 删除保存的数据
sessionStorage.removeItem('key');
// 从 sessionStorage 删除所有保存的数据
sessionStorage.clear();
// 获取某个索引的Key
sessionStorage.key(index)
3. cookie
Cookie是最早被提出来的本地存储方式,在此之前,服务端是无法判断网络中的两个请求是否是同一用户发起的,为解决这个问题,Cookie就出现了。
- 存储时间:存储时间有限制,它的生存时间由 expires 属性指定
- 存储大小:大约只有4KB,存储大小很小,每个域名下的cookie存储数量不能超过20个
- 每次HTTP请求会携带
- 受制于同源策略的局限下
- 有安全问题,如果Cookie被拦截了,那就可获得session的所有信息,即使加密也于事无补,不用知道cookie的意义,只要转发cookie就能达到目的
如果需要域名之间跨域共享cookie,有两种方法:
- 使用nginx反向代理
- 在一个站点登陆之后,往其他网站写Cookie。服务端的Session存储到一个节点,Cookie存储sessionId
使用场景:
- cookie一般与session一起使用,存储sessionId,每次向服务器端发送请求时,携带上sessionId,服务器端知道是谁发起的请求
- 可以统计页面点击次数
4. IndexedDB
IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象(blobs))。该 API 使用索引实现对数据的高性能搜索。虽然 localStorage 与 sessionStorage 在存储较少量的数据很有用,但对于存储更大量的结构化数据来说力不从心。而 IndexedDB 提供了这种场景的解决方案。
-
键值对存储:IndexedDB 允许存储和检索用键索引的对象;只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务。
-
使用 IndexedDB 执行的操作是异步执行的,以免阻塞应用程序。
-
支持事务:IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
-
同源限制:IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
-
储存空间大:IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。
-
支持二进制储存:IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。
2、cookie有哪些字段,作用分别是什么?
客户端向服务器端发送请求,服务器端可以设置set-cookie来发送给客户端,客户端每次请求需要将此信息发送给服务器端。
1. cookie的生命周期:
- 会话期:在当前会话结束后删除,浏览器定义了“当前会话”结束的时间,一些浏览器重启时会使用会话恢复,这可能导致会话 cookie 无限延长。
- 持久性:Cookie 在过期时间(
Expires)指定的日期或有效期(Max-Age)指定的一段时间后被删除。
2. 关于安全问题:
Secure属性的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端。它永远不会使用不安全的 HTTP 发送(本地主机除外),这意味着中间人攻击者无法轻松访问它。但是,Secure不会阻止对 cookie 中敏感信息的访问。例如,有权访问客户端硬盘的人可以读取和修改它- JavaScript
Document.cookieAPI 无法访问带有HttpOnly属性的 cookie;此类 Cookie 仅作用于服务器。此预防措施有助于缓解跨站点脚本(XSS)攻击。
3. 常用的字段:
domain:Domain指定了哪些主机可以接受 CookiePath:Path属性指定了一个 URL 路径,该 URL 路径必须存在于请求的 URL 中,以便发送Cookie标头SameSite:SameSite属性允许服务器指定是否/何时通过跨站点请求发送(其中站点由注册的域和方案定义:http 或 https)。这提供了一些针对跨站点请求伪造攻击(CSRF)的保护。它采用三个可能的值:Strict、Lax和None。- 使用
Strict,cookie 仅发送到它来源的站点。 Lax与 Strict 相似,只是在用户导航到 cookie 的源站点时发送 cookie。例如,通过跟踪来自外部站点的链接。如果没有设置SameSite属性,则将 cookie 视为Lax。None指定浏览器会在同站请求和跨站请求下继续发送 cookie,但仅在安全的上下文中(即,如果SameSite=None,且还必须设置Secure属性)。
- 使用
3、在无痕模式下使用localStorage、sessionStorage会怎样?
在无痕模式下使用storage,storage仍然存在,只不过在使用setItem时会报错,所以可以将需要存储的内容,存储到window下进行全局存储,当使用无痕模式时,进行调用全局存储的值
try {
sessionStorage.setItem('private_test', 1);
} catch (e) {
//无痕模式
}
// 隐私模式下面,把临时值存到window.name中去
function NameStorage(type) {
this.store = NameStorage[type];
}
Object.assign(NameStorage.prototype, {
getItem: function(key) {
return this.store[key];
},
setItem: function(key, value) {
this.store[key] = value;
this._saveNameValue();
},
removeItem: function(key) {
delete this.store[key];
this._saveNameValue();
},
clear: function() {
this.store = {};
this._saveNameValue();
},
_saveNameValue: function() {
let ret = {
session: NameStorage.session,
local: NameStorage.local
}
window.name = JSON.stringify(ret);
}
});
上面会把所有的 storage 中数据存储到window.name上去,然后在每个页面启动时,调用一下keepName方法,把window.name的数据拿下来放到NameStorage上面。这时候,只需要调用new NameStorage(‘local’)来代替localStorage进行操作就行了
function keepName () {
if (keepName.done) {
return;
}
let ret;
if (window.name) {
try {
ret = JSON.parse(window.name);
} catch (e) {
ret = {};
}
}
if (!_.isPlainObject(ret)) {
ret = {};
}
if (!ret.session) {
ret.session = {};
}
if (!ret.local) {
ret.local = {};
}
NameStorage.session = ret.session;
NameStorage.local = ret.local;
keepName.done = true;
}
4、浏览器怎么对HTML5离线存储资源进行管理和加载的?
-
在线的情况下,浏览器发现 html 头部有 manifest 属性,它会请求 manifest 文件,如果是第一次访问 app ,那么浏览器就会根据 manifest 文件的内容下载相应的资源并且进行离线存储。如果已经访问过 app 并且资源已经离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的 manifest 文件与旧的 manifest 文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,那么就会重新下载文件中的资源并进行离线存储。
-
离线的情况下,浏览器就直接使用离线存储的资源