1.前端存储数据的好处
通过把数据存储在浏览器中,用户不必每次都向服务器请求获取同一个信息。甚至在离线的情况下,也可以获取本地存储的数据而不是通过服务端获取数据;
减少请求次数,减轻服务端压力;
数据随用随取,不用过度依赖于服务端;
2.前端需要存储什么数据
根据不同情况存储需要的数据,如用户的信息(用户名,用户id,用户身份等),需要保留的操作数据(如用户在某次选择中需要记录的数据)
3.前端存储的数据在哪里可以看到
4.前端存储数据的方式
- Cookie
- localStorage
- sessionStorage
- indexedDB
5.Cookie
1)什么是Cookie
当用户浏览器向服务器发送请求时,服务器会返回给用户浏览器一小块数据,用户浏览器会将这一小块数据存储在本地,在下一次向同一个服务器发起请求时会携带上这一小块数据,告知服务端这两个请求是否来自同一浏览器。值得一提的是,一开始Cookie被发明出来并不是为了给浏览器存储数据,而是为了解决http协议的无标记状态问题:用户的两次 HTTP 请求,服务端并不能通过请求本身,知道这两次请求,来自于同一个用户。

2)Cookie的组成
- 名称:一个唯一确定cookie的名称
- 值:存储在cookie中的字符串值,值必须被URL编码
- 域:cookie对于哪个域是有效的,所有向该域发送的请求都会包含这个cookie信息
- 路径:对于指定域中的路径,应该向服务器发送cookie
- 失效时间:表示cookie何时应该被删除的时间戳
如:
username = Bill Gates
3)js创建Cookie
//js创建Cookiedocument.cookie = "username=Bill Gates";document.cookie = "username=John Doe; expires=Sun, 31 Dec 2017 12:00:00 UTC";//js获取Cookievar x = document.cookie;//js删除Cookie//不用指定Cookie,直接将expires参数设置为过去的日期即可document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
例子:
//设置Cookiefunction setCookie(cname, cvalue, exdays) {var d = new Date();d.setTime(d.getTime() + (exdays*24*60*60*1000));var expires = "expires="+ d.toUTCString();document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";}// 清除cookieclearAllCookie: function () {var keys = document.cookie.match(/[^ =;]+(?=\=)/g);if (keys) {for (var i = keys.length; i--;)document.cookie = keys[i] + '=0;expires=' + new Date(0).toUTCString()}},//获取CookiegetCookie: function (name) {var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");if (arr = document.cookie.match(reg))return unescape(arr[2]);elsereturn null;},
4)Cookie的缺点:
- Cookie需要在客户端和服务器端之间来回传送,会浪费不必要的资源
- Cookie的存储大小有限制,对于每个域,一般只能设置20个cookie,每个cookie大小不能超过4KB
- Cookie的安全性,cookie因为保存在客户端中,其中包含的任何数据都可以被他人访问,cookie安全性比较低
6.localStorage
是一种持久化的存储方式,如果不手动清除,数据永远不会过期。它也是采用Key - Value的方式存储数据,按域名将数据分别保存到对应数据库文件里。
- 保存的数据长期存在,下一次访问该网站的时候,网页可以直接读取以前保存的数据。
- 大小为5M左右。
- 仅在客户端使用,不和服务端进行通信。
- 存储的信息在同一域中是共享的。
设置:localStorage.setItem('name': 'xs')获取:localStorage.getItem('name')删除:localStorage.removeItem('name');
7.sessionStorage
对象值存储会话数据,其生命周期会存储到浏览器关闭。(在该过程中刷新页面其数据不受影响),使用方法与localStorage一致。
8.sessionStorage和localStorage区别:
- localStorage是永久存储,除非手动删除。sessionStorage当会话结束(当前页面关闭的时候,自动销毁)
- localStorage只要在相同的协议、相同的主机名、相同的端口下,就能读取/修改到同一份localStorage数据。
9.indexedDB
优点:
- 存储数据理论上没有上线
- 所有操作都是异步,比同步操作性能更高,尤其是数据量大的情况下
- 原生支持存储js对象
- 以数据库的形式储存数据,数据管理更规范
10.浏览器的缓存
浏览器的缓存是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。
这种size大小不为0的请求,就是没有使用缓存。size是memory cache 和 disk cache就表示,浏览器并没有向服务器发送请求,而是直接读取了本地的缓存资源文件。
11.浏览器的缓存类型
- memory cache
- disk cache
memory cache:内存缓存,即使我们不设置缓存,当前的内存空间比较充裕的话,一些资源还是会被缓存下来。但这种缓存是暂时的,一旦关闭了浏览器,这一部分用于缓存的内存空间就会被释放掉。
内存缓存虽然比较高效,但还是受限于计算机内存的大小,所以能让我们使用的内存并不多,这个时候就需要硬盘来存储大量的缓存。
disk cache:存储在硬盘中的缓存,时效比较长,它会根据HTTP Header中设置的字段类型,来判断资源是否需要重新请求
12.缓存过程
浏览器在第一次请求资源后,会获取到请求的结果以及缓存标识,接下来,浏览器会根据第一次请求返回的响应头来确定缓存处理的方式,分别是强缓存和协商缓存

- 浏览器会先获取该资源缓存的header信息,根据其中的expires和cache-control判断是否命中强缓存,若命中则直接从缓存中获取资源,包括缓存的header信息,本次请求不会与服务器进行通信;
- 如果没有命中强缓存,浏览器会发送请求到服务器,该请求会携带第一次请求返回的有关缓存的header字段信息(Last-Modified/IF-Modified-Since、Etag/IF-None-Match),由服务器根据请求中的相关header信息来对比结果是否命中协商缓存,若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取;否则返回最新的资源内容
13.强缓存
强缓存是利用http的返回头中的Expires或者Cache-Control两个字段来控制的,用来表示资源的缓存时间
如Cache-Control:max-age=3600,代表着资源的有效期是3600秒。
- no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
- no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
- public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
- private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。
14.协商缓存
协商缓存就是由服务器来确定缓存资源是否可用,客户端与服务器端通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问,即第一次请求的响应头带上某个字段(Last-Modified或者Etag),则后续请求则会带上对应的请求字段(If-Modified-Since或者If-None-Match),若响应头没有Last-Modified或者Etag字段,则请求头也不会有对应的字段。
服务器第一次返回资源时,会返回Last-Modified属性,表示改资源最后被更改的时间;浏览器第二次请求该资源时,会向服务端发送If-Modified-Since属性,询问该时间之后资源文件是否被修改过。
或者服务器第一次返回资源时,会返回Etag(资源文件的唯一标识,只要资源有变化,Etag就会重新生成),浏览器二次请求时会返回If-None-Match,服务端根据接收到的If-None-Match和之前的Etag进行对比,判断资源是否进行过修改,如果修改,则返回新的资源,否则命中协商缓存,返回304状态,从缓存中获取资源。
思考:为什么有了Last-Modified还需要Etag进行判断?
如图可以看出,Last-Modified返回的最小时间单位是秒,所以,服务器的资源和本地的资源有可能存在不一致,如果请求的时机正好在资源变动的1s之内,ETag使用的是唯一标识,能够很好的解决这个问题。
15.缓存方式总结
| 缓存类型 | 获取资源形式 | 状态码 | 发送请求到服务器 |
|---|---|---|---|
| 强缓存 | 从缓存取 | 200(from cache) | 否,直接从缓存取 |
| 协商缓存 | 从缓存取 | 304(Not Modified) | 是,通过服务器来告知缓存是否可用 |
- html文件千万不能设置强缓存,目前前端开发页面,大多数情况下都是单页面应用,一旦有变动及时更新成功,所以html应该设置cache-control为no-cache。
- CSS、JS、图片等资源,可以设置一个长时间的强缓存。在资源名(或者路径)中添加 hash, 版本号等动态字符,这样在更改资源的时候,可以通过更改这些动态字符来通知浏览器直接去请求新的资源,在文件不变动的情况下,直接使用本地缓存,不去向浏览器请求。
16.浏览器清除缓存
1)html中加上
2)页面中引用js的地方加上随机数//不缓存<META HTTP-EQUIV="pragma" CONTENT="no-cache"><META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate"><META HTTP-EQUIV="expires" CONTENT="0">
3)强制刷新 (Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache,服务器直接返回 200 和最新内容。URL 参数后加上 "?ran=" + Math.random(); //当然这里参数 ran可以任意取了URL 参数后加上 "?timestamp=" + new Date().getTime();
4)禁止强制缓存
5)nginx清除缓存
在nginx.conf加入如下规则:
server {location ~* \.(html)$ {access_log off;add_header Cache-Control max-age=no-cache;}location ~* \.(css|js|png|jpg|jpeg|gif|gz|svg|mp4|ogg|ogv|webm|htc|xml|woff)$ {# 同上,通配所有以.css/.js/...结尾的请求access_log off;add_header Cache-Control max-age=360000;}}
17.参考文献
https://zhuanlan.zhihu.com/p/93357692
https://www.jianshu.com/p/54cc04190252
https://www.cnblogs.com/tugenhua0707/p/10841267.html
