缓存
1. 位置
我们浏览器查找缓存会有优先级:
1. Service Worker
2. Memory Cache
3. Disk Cache
4. Push Cache
5. 网络请求
在上一篇博文,我们已经介绍过Service Worker,我们可以利用。
如果我们定义了Service Worker,那么,所有请求都先走它。
如果 Service Worker 的缓存不能命中,那么就会通过 fetch 发出请求。
而 fetch 会先依次尝试查找各个缓存。
Memory Cache
Memory Cache,顾名思义是存到内存的缓存,这里的缓存当然非常快。一般小文件会缓存到这,,同时缓存到 Disk Cache。
页面被关闭前,再次访问都会访问 Memory Cache。
如果页面被关闭,Memory Cache 就会被释放,然后下次打开就会访问 Disk Cache。
Disk Cache
Disk Cache,就是缓存到硬盘,这个会比 Memory Cache 慢一些,但是时效性强。一般大文件首次加载就缓存到这。
Push Cache
这个是 HTTP 2 的一个特性,博主也不怎么了解,就不误人子弟了。
推荐阅读:https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/
网络请求
最后实在没办法了,就只能真发出去请求,去获取资源了。
2. 策略
缓存策略分为2种:强缓存 和 协商缓存, 都是通过 http header 来实现的。
强缓存
通过 Expires 和 Cache-control 来实现。
Expires 是 HTTP 1.0 的产物,例如
Expires: Wed, 22 Oct 2018 08:41:00 GMT
表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT
后过期,需要再次请求。并且 Expires
受限于本地时间,如果修改了本地时间,可能会造成缓存失效。
Cache-control 是 HTTP 1.1 的产物,优先级高于 Expires ,例如
Cache-control: max-age=30
表示该资源会在 30 秒后过期,需要再次请求。
其中很重要的2个属性 max-age 和 no-cache
max-age 指定缓存生效的时间,时间过去才会失效;no-cache 会缓存,但是马上失效,以后都会进行协商缓存。
至于 Cache-control 还有什么值,详细请看我之前写过的博文:点击查看
协商缓存
协商缓存是出现在缓存失效的时候,它是通过 Last-Modified, If-Modified-Since 和 Etag, If-None-Match 来实现的。
Last-Modified 和 If-Modified-Since 是 HTTP 1.0 的产物,表示文件最后修改日期。
If-Modified-Since 会将 Last-Modified
的值发送给服务器,询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来,否则返回 304 状态码。
但是它会有些弊端:
1. 以秒为单位,如果 1s 内修改了好几次,这就无法感知到了。
2. 如果一个文件只是打开保存,并没有修改,但是服务器还是认为被修改了。
Etag 和 If-None-Match 是 HTTP 1.1 的产物,是为了解决 Last-Modified 的问题而出现的,优先级比 Last-Modified 高,相当文件的一个特征值(例如文件的md5)
If-None-Match 会将 Etag 的值发给服务器,询问服务器文件的特征值是否和发过来的一致,如果不一致说明文件更新了,返回新的资源,否则返回304。
3.默认缓存时间
如果文件没设置强缓存的缓存策略,那浏览器会用 Date - Last-Modified 的时间的 10% 作为缓存时间。
意思大概是,更新时间越古老的文件,缓存时间越长。
4. 实际使用
频繁修改的文件: Cache-control: no-cache,每次请求都采用协商缓存。
代码文件:Cache-control: max-age=31536000,代码文件缓存一直缓存,因为一般webpack打包后都会修改文件名,后面跟着一串hash