了解前端缓存, 收获不止于此!
这次我们来讲一下关于前端缓存的问题. 感谢赵欢同学提供 doc 素材.
首先, 开局我画了一张图, 你会对文章有一个大局了解.
今天讲的是前端缓存.
前端缓存有 3 大种: 如图, 分为 HTTP 缓存, 浏览器缓存, 应用程序缓存.
HTTP 缓存
我们先来看 HTTP 缓存:(做下了解)
分为强缓存与协商缓存.
首先看强缓存:
强缓存之 Expires:
值为服务端返回的到期时间, 即下一次请求时, 请求时间小于服务端返回的到期时间, 直接使用缓存数据;
到期时间是由服务端生成的, 客户端时间跟服务端时间可能存在误差, 这就会导致缓存命中的误差;
被 Cache-Control 替代;
强缓存之 Cache-Control:
参数
|
说明
|
public
|
所有内容都将被缓存 (客户端和代理服务器都可缓存)
|
private
|
内容只缓存到私有缓存中 (仅客户端可以缓存,代理服务器不可缓存)
|
no-cache
|
必须先与服务器确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。因此,如果存在合适的验证令牌 (ETag),no-cache 会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载。
|
no-store
|
所有内容都不会被缓存到缓存或 Internet 临时文件中
|
must-revalidation/proxy-revalidation
|
如果缓存的内容失效,请求必须发送到服务器 / 代理以进行重新验证
|
max-age=xxx
|
缓存的内容将在 xxx 秒后失效, 这个选项只在 HTTP 1.1 可用, 并如果和 Last-Modified 一起使用时, 优先级较高
|
来举个栗子:
图中 Cache-Control 仅指定了 max-age, 所以默认为 private, 缓存时间为 31536000 秒(365 天)
也就是说, 在 365 天内再次请求这条数据, 都会直接获取缓存数据库中的.
协商缓存:(相当于就是浏览器与服务器通过一个值作为更新 flag, 一个协商一个判断)
协商缓存之 Etag/If-None-Match:
当浏览器请求服务器的某项资源 (A) 时, 服务器会根据 A 算出一个哈希值, 并通过 Etag 返回给浏览器, 浏览器把 ETAG 和资源 A 同时缓存到本地.
当下次向服务器请求该资源时, 会通过 If-None-Match 把 ETAG 发送给服务器.
服务器再次计算 A 的哈希值并和浏览器的返回值作比较, 如果 A 发生了变化就把 A 返回给浏览器(返回值 200), 如果未发生变化就返回浏览器 304(未修改)
协商缓存之 Last-Modified/If-Modified-Since:
在浏览器请求服务器的某项资源时, 返回资源的同时还有一个 Last-Modified 的属性标记此文件在服务器端的最后修改时间;
浏览器第二次访问该资源时, 会向服务器传送 If-Modified-Since 报头, 询问该时间之后文件是否被修改过;
如果服务器的资源没有变化, 则时间一致, 返回 304 的状态吗, 浏览器使用本地缓存;
如果时间不一致, 返回 200, 显示新文件并缓存.
那么 Etag 和 Last-Modified, 他们之间有什么区别呢???
Etag 是标识传输, Last-Modified 是时间传输;
Etag 的优先级高于 Last-Modified;
Last-modified 标注的最后修改时间只能精确到秒, 如果文件在 1 秒以内被多次修改, 它不能准确标注文件的最后修改时间;
如果文件定期生成, 但内容没有任何变化, 但是 last-modified 却改变了, 导致没法使用缓存;
有可能存在服务器没有准确获取文件修改时间, 或与代理服务器时间不一致的情况;
etag 每次服务端生成都需要进行读写操作, 而 last-modified 只需要读取操作, etag 消耗更大些;
各有优劣!
那强缓存与协商缓存, 他们的规则分别是什么?
强缓存规则:
已失效时, 请求服务器, 服务器返回数据和缓存规则, 客户端将数据和缓存规则存入缓存数据库;
未失效时, 请求缓存数据库, 返回数据并渲染;
协商缓存规则:
先到缓存数据库中获取标识 Etag/Last-Modified,
再通过 If-None-Match/If-Modified-Since 字段带上缓存标识请求服务器, 服务器判断内容是否失效;
这两种缓存的执行流程是怎么样的?
强缓存未失效, 从缓存中读取数据, cache-control 优先级高于 Expires;
强缓存已失效, 执行协商缓存, Etag 的优先级高于 last-Modified;
缓存未失效从缓存中读取数据返回 304 状态码;
缓存已失效返回资源和 200 状态码;
怎么清除缓存?
浏览器默认会缓存图片, CSS 和 JS 等静态资源, 所以开发环境下经常会因为强缓存导致资源没有及时更新而看不到最新的效果, 需要清除缓存可以使用一下几种方法:
直接 ctrl+f5, 这个办法能解决页面直接引用的资源更新的问题;
使用 ctrl+shift+delete 清除缓存;
如果用的是 Chrome, 可以 F12 在 network 那里把缓存给禁掉, 选中 "disable Cache":
或者给资源文件加一个时间戳;
或者禁止修改 html 中的缓存字段为禁止使用;
或者在谷歌浏览器刷新按钮上, 点击右键, 选择 "清空缓存并硬性重新加载";
浏览器缓存
然后是浏览器缓存:(这个前端很多时候会用到)
有本地小容量存储与本地大容量存储
小容量的 Cookie:
一般用于以下场景:
记住用户名密码
欢迎语
小容量的 LocalStorage:
记录后只要不手动清除就会一直存在.
小容量的 SessionStorage:
仅在本次会话时有效. 关闭当然窗口后就没有了.
Storage 的 API 如下:(localStorage 为例, sessionStorage 一样)
保存数据:(3 种写法均可)
写法 1:
localStorage.setItem("key",value)
写法 2:
localStorage["key"]=1
写法 3:
localStorage.key=1
读取数据:(相对也有 3 种)
写法 1:
var value=localStorage.getItem("key")
写法 2:
var value=localStorage["key"]
写法 3:
var value=localStorage.key
删除单个数据:
localStorage.removeItem(key);
删除所有数据:
localStorage.clear();
得到某个索引的 key:
localStorage.key(index);
比较一下 Cookie,LocalStorage,sessionStorage 的异同:
cookie 会在在同源的 http 请求中携带, 不能超过 4K, 参与和服务器交互;
sessionStorge 和 locaStorage 保存数据在本地, 限制最多 5M, 不参与和服务器交互;
sessionStorage 仅在当前窗口关闭前有效;
localstorage 会一直保存在浏览器中, 除非手动删除;
cookie 在设置过期时间之前一直有效, 不设置过期时间窗口关闭则清除;
sessionStorage 不在不同的浏览器窗口中共享, 即使是同一个页面,
localstorage 和 cookie 在所有同源窗口中共享
本地大容量存储之 webSql:
表保存数据, 用 sql 操作数据库(写的是 sql 语句, 懂 MySQL 数据库的完全不在话下)
创建表:
create table if not exists product(id integer primary key autoincrement,name text not null,price double);
添加一条数据:
- insert into product(name,price) values('斗战圣皇','1.2');
- insert into product(name,price) values('布衣神探: 最后的证据','0.9');
删除一条数据:
delete from product where id=2;
更新一条数据:
update product set name='斗战圣皇第二部',price='0.99' where id=1;
查询表格:
select * from product;
删除表格:
drop table IF EXISTS product;
本地大容量存储之 IndexDB:
保存的是对象类型的数据
open()打开或创建数据库
deleteDatabase()删除数据库;
transaction()打开事物
add()添加数据
get()查找数据
delete()根据 ID 删除数据
clear()清除全部数据
应用程序缓存
分为应用缓存和 PWA
什么是应用缓存?
页面基本结构:
HTML 标签上配置 manifest 文件, 文件后缀. appcache;
manifest 需要配置 MIME-type, 即 "text/cache-manifest". 必须在 Web 服务器上进行配置, 不同服务器不一样;
如 tomcat 需要修改 conf/Web.xml 配置文件, 添加:
- <mime-mapping>
- <extension>
- manifest
- </extension>
- <mime-type>
- text/cache-manifest
- </mime-type>
- </mime-mapping>
manifest 文件的格式个配置, 分三部分, 缓存文件, 不缓存文件, 页面无法访问时的回退页面;
CACHE MANIFEST
/theme.HTML
NETWORK:
login.PHP
- FALLBACK:
- /HTML/ /offline.HTML
举个栗子:
有网络时:
什么是 PWA?
先了解 App 和 Web 网页存在的一些不足:
App 应用存在的不足:
开发成本高(iOS 和安卓)
软件上线需要审核
版本更新需要上传到应用商店
想使用 App 必须下载
Web 网页存在的不足:
手机桌面入口不够便捷, 需要记住 URL 或加入书签
不能像 App 一样推送消息
PWA 弥补了 App 和 Web 网页存在的一些缺点:
是一个 Web 网页应用
可以添加至主屏幕, 点击主屏幕的图标可以实现启用动画以及隐藏地址栏
实现了离线缓存功能, 即使手机没有网络, 依然可以实现一些离线功能
实现了消息推送
一个简单的 PWA 栗子:
来源: http://www.bubuko.com/infodetail-3033898.html