🥇 浏览器储存量的支持
链接:http://dev-test.nemikor.com/web-storage/support-test/
🥇 浏览器存储
Cookie, SessionStorage, LocalStorage 这三者都可以被用来在浏览器端存储数据,而且都是字符串类型的键值对!
注意:session 和 SessionStorage 不是一个概念!!!在服务端有一种存储方式叫做:session 会话存储,常常被简称session
后期Node课程中会对cookie和session会话存储进行详细讲解
🥇 Web Storage
SessionStorage和LocalStorage都是浏览器本地存储,统称为Web Storage,存储内容大小一般支持5-10MB
浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制。
相关API:
1. localStorage.setItem('key', 'value');
该方法接受一个键名和值作为参数,将会把键值对添加到存储中,如果键名存在,则更新其对应的值。
2. var data = xxxxxStorage.getItem('person');
该方法接受一个键名作为参数,返回键名对应的值。
3. xxxxxStorage.removeItem('key');
该方法接受一个键名作为参数,并把该键名从存储中删除。
4. xxxxxStorage.clear()
调用该方法会清空存储中的所有键名
备注:SessionStorage存储的内容会随着浏览器窗口关闭而消失。
LocalStorage存储的内容,需要手动清除才会消失。
storage事件:
1. Storage对象发生变化时触发(即创建/更新/删除数据项时,Storage.clear() 只会触发一次)
2. 在同一个页面内发生的改变不会起作用
3. 在相同域名下的其他页面发生的改变才会起作用。(修改的页面不会触发事件,与它共享的页面会触发事件)
key : 修改或删除的key值,如果调用clear(),为null
newValue : 新设置的值,如果调用clear(),为null
oldValue : 调用改变前的value值,如果调用clear(),为null
url : 触发该脚本变化的文档的url
storageArea : 当前的storage对象
使用方法:
window.addEventListener('storage',function (event) {
//此处写具体业务逻辑
})
🥇 跨页签通讯
input.onblur = function () {
localStorage.setItem('demo', input.value)
}
window.addEventListener('storage', function (event) {
console.log(event);
let val = document.getElementById('val');
val.value = event.newValue;
})
🥇 缓存
🥈 缓存理解
缓存定义:
- 浏览器在本地磁盘上将用户之前请求的数据存储起来,当访问者再次需要改数据的时候无需再次发送请求,直接从浏览器本地获取数据
缓存的好处:
- 减少请求的个数
- 节省带宽,避免浪费不必要的网络资源
- 减轻服务器压力
- 提高浏览器网页的加载速度,提高用户体验
🥈 缓存分类
强缓存
- 不会向服务器发送请求,直接从本地缓存中获取数据
- 请求资源的的状态码为: 200 ok(from memory cache)
协商缓存
- 向服务器发送请求,服务器会根据请求头的资源判断是否命中协商缓存
- 如果命中,则返回304状态码通知浏览器从缓存中读取资源
强缓存 & 协商缓存的共同点
- 都是从浏览器端读取资源
强缓存 VS 协商缓存的不同点
- 强缓存不发请求给服务器
- 协商缓存发请求给服务器,根据服务器返回的信息决定是否使用缓存
🥈 缓存使用示意图
🥈 缓存中的 header 参数
🥉 强缓存的 header 参数
expires:
- 这是http1.0时的规范;它的值为一个绝对时间的GMT格式的时间字符串,如
Mon, 10 Jun 2015 21:31:12 GMT
,如果发送请求的时间在expires之前,那么本地缓存始终有效,否则就会发送请求到服务器来获取资源
- 这是http1.0时的规范;它的值为一个绝对时间的GMT格式的时间字符串,如
cache-control:max-age=number
- 这是http1.1时出现的header信息,主要是利用该字段的max-age值来进行判断,它是一个相对值;资源第一次的请求时间和Cache-Control设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行;
- cache-control常用的值(做一个简单了解即可):
- no-cache: 不使用本地缓存,需要使用协商缓存。先与服务器确认返回的响应是否被更改,如果之前的响应中存在Etag,那么请求的额时候会与服务器端进行验证,如果资源为被更改则使用缓存。
- no-store: 直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
- public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
- private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。
- 注意:当cache-control与Expires共存的时候cache-control的优先级高
🥉 协商缓存的 header 参数
重点:协商缓存都是由服务器来确定缓存资源是否可用的,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问
Last-Modified/If-Modified-Since:二者的值都是GMT格式的时间字符串
1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上Last-Modified的header,这个header表示这个资源在服务器上的最后修改时间
2. 浏览器再次跟服务器请求这个资源时,在request的header上加上If-Modified-Since的header,这个header的值就是上一次请求时返回的Last-Modified的值
3. 服务器再次收到资源请求时,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。当服务器返回304 Not Modified的响应时,response header中不会再添加Last-Modified的header,因为既然资源没有变化,那么Last-Modified也就不会改变,这是服务器返回304时的response header
4. 浏览器收到304的响应后,就会从缓存中加载资源
5. 如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modified的Header在重新加载的时候会被更新,下次请求时,If-Modified-Since会启用上次返回的Last-Modified值
Etag / If-None-Match
1. 这两个值是由服务器生成的每个资源的唯一标识字符串,只要资源有变化就这个值就会改变
2. 其判断过程与Last-Modified/If-Modified-Since类似
既生 Last-Modified 何生 Etag
1. HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题
2. 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET
3. 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
4. 某些服务器不能精确的得到文件的最后修改时间。
🥉 小结
利用Etag能够更加准确的控制缓存,因为Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符。
Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
🥈 强缓存如何重新加载新的资源
通过更新页面中引用的资源路径,让浏览器主动放弃加载缓存去加载新的资源
示例:https://www.baidu.com/s?t=7aec0h3KB3Ba8lAbuyPg0AC0eDa59IvtDSmtMQBc6eW
好处:
1. 每次文件改变后 query 的值就会发生修改,当 query 值不同的时候也就是页面引用的资源路径不同。此时浏览器会主动加载新的资源。
🥇 Cookie
🥈 是什么?
本质就是一个【字符串】,里面包含着浏览器和服务器沟通的信息(交互时产生的信息)。
存储的形式以:【key-value】的形式存储。
浏览器会自动携带该网站的cookie,只要是该网站下的cookie,全部携带。
🥈 分类:
会话cookie(关闭浏览器后,会话cookie会自动消失,会话cookie存储在浏览器运行的那块【内存】上)。
持久化 cookie:(看过期时间,一旦到了过期时间,自动销毁,存储在用户的硬盘上,备注:如果没有到过期时间,同时用户清理了浏览器的缓存,持久化cookie也会消失)。
🥈 工作原理:
当浏览器第一次请求服务器的时候,服务器可能返回一个或多个cookie给浏览器
浏览器判断cookie种类
1. 会话cookie:存储在浏览器运行的那块内存上
2. 持久化cookie:存储在用户的硬盘上
以后请求该网站的时候,自动携带上该网站的所有cookie(无法进行干预)
服务器拿到之前自己“种”下的 cookie,分析里面的内容,校验 cookie 的合法性,根据 cookie 里保存的内容,进行具体的业务逻辑。
🥈 应用:
解决http无状态的问题(例子:7天免登录,一般来说不会单独使用cookie,一般配合后台的session存储使用)
🥈 不同的Cookie
不同的语言、不同的后端架构 cookie 的具体语法是不一样的,但是 cookie 原理和工作过程是不变的。
备注:cookie不一定只由服务器生成,前端同样可以生成cookie,但是前端生成的cookie几乎没有意义。
🥈 对比浏览器的本地存储:
localStorage:
1. 保存的数据,只要用户不清除,一直存在
2. 作为一个中转人,实现跨页签通信。
3. 保存数据的大小:5MB~10MB
sessionStorage:
1. 保存的数据,关闭浏览器就消失
2. 保存数据的大小:5MB~10MB
cookie:
1. 分类:会话cookie( 关浏览器消失 )、持久化cookie( 到过期时间消失 )
2. 保存数据的大小:4K~8K
3. 主要用于解决http无状态( 一般配合后端的 session 会话存储使用 )
4. 浏览器请求服务器时,会自动携带该网站的所有 cookie
🥈 Cookie 操作 - 服务端
基于 Node 和 Express 使用 Cookie
// express 中给客户端 “种” cookie不需要任何的库
let obj = {name:'chen',age:25}
res.cookie('xx',JSON.stringify(obj)) // 给客户端种下一个会话 cookie
res.cookie('xx',JSON.stringify(obj),{maxAge:1000 * 60 * 60 *24 *30}) //给客户端种下一个持久化 cookie 持续一个月
//express 中读取客户端携带过来的 cookie 要借助一个中间件,名为:cookie-parser
let cookieParser = require('cookie-parser')
app.use(cookieParser())
app.get('/demo',function (req,res) {
const {xx} = req.cookies
})
// 删除 Cookie
app.get('/demo',function (req,res) {
res.cookie('xx','',{maxAge:0}) // 第一种删除方式
res.clearCookie('peiqi') // 第二种删除方式
})
🥇 session - 服务端
基于 Node 和 Express 使用 session
操作session(cookie 配合session):
1.下载安装:npm i express-session --save 用于在 express 中操作 session
2.下载安装:npm i connect-mongo --save 用于将 session 写入数据库(session 持久化)
3.引入 express-session 模块:
const session = require('express-session');
4.引入 connect-mongo 模块:
const MongoStore = require('connect-mongo')(session);
5.编写全局配置对象:
app.use(session({
name: 'userid', // 设置cookie 的name,默认值是:connect.sid
secret: 'qianming', // 参与加密的字符串(又称签名)
saveUninitialized: false, // 是否在存储内容之前创建会话
resave: true ,// 是否在每次请求时,强制重新保存session,即使他们没有变化
store: new MongoStore({
url: 'mongodb://localhost:27017/sessions_container',
touchAfter: 24 * 3600 // 修改频率(例:// 在24小时之内只更新一次)
}),
cookie: {
httpOnly: true, // 开启后前端无法通过 JS 操作 cookie
maxAge: 1000*30 // 设置 cookie 的过期时间
},
}));
6.向 session 中添加一个 xxxx,值为yyy req.session.xxxx = yyy
7.获取 session 上的xxx 属性:const {xxx} = req.session
整个过程是:
1.客户端第一次发起请求,服务器开启一个session专门用于存储这次请求的一些信息。
2.根据配置对象的信息,服务器决定是否进行:session持久化等其他操作。
2.与此同时服务器创建了一个cookie,它的key我们可以自己指定,但是它的value一定是上一步session的唯一标识。
3.服务器将我们指定好的内容添加进session对象,例如:req.session.xxx = yyy。
4.等请求再次过来时,客户端的请求中包含着之前 “种” 的cookie。
5.服务器检查携带过来的cookie是否有效,决定是否去读取对应session中的信息。