增量更新是目前大部分团队采用的缓存更新方案,能让用户在无感知的情况获取最新内容。具体实现方式通常是(一般我们通过构建工具来实现,比如webpack
):
- 构建产出文件hash(如:
index.d94f83fac22c203b788c.css
) - 更新
html
文件里静态资源的引用URL
由于其他资源是由html文件直接或间接引用才可以被加载,如果html里的静态资源URL更新了,那请求的肯定就是最新资源了。那我们需要考虑的就是如何确保加载的html是最新的了,其他的静态资源就充分利用浏览器缓存以减少网络请求提高web性能。浏览器缓存实质就是HTTP缓存,而HTTP缓存分为强缓存
和协商缓存
。
强缓存
强缓存不会发送请求,直接从浏览器加载资源。是否命中强缓存根据HTTP Response头部Expires
、Cache-Control
(max-age
)来判断。
-
Expires
通过返回一个过期时间来判断是否过期,在此时间之前浏览器直接从缓存加载资源。但其缺点是返回的过期时间为服务器时间,而比较是同客户端时间比较,如果服务端和客户端存在时间误差就不准了。 -
max-age
返回的时间过期时间跨度,比如max-age=3600告诉浏览器接下来的1小时内使用缓存。这样就解决了Expires
时间误差导致的问题。
强缓存命中优先判断max-age
,max-age
优先级大于Expires
,判断流程如下:
协商缓存
-
Etag
和If-None-Match
Etag的值是根据一定算法生成的字符串,用以判断文件是否更改,类似于文件hash。在第一次访问时,服务会返回该文件的Etag值,在之后的访问通过在请求头增加If-None-Match参数,把Etag的值带过去,服务器通过比较Etag的值来判断是否需要重新返回最新资源(200 or 304)。 -
Last-Modified
和If-Modified-Since
Last-Modified为该资源文件的最后修改时间。同样在第一次返回,之后通过If-Modified-Since带过去,服务器通过比较值来判断是否需要返回最新资源。
如果 If-None-Match
和 If-Modified-Since
都有,则必须一次性都发给服务器,没有优先级,实际中比较ETag
就够了。如果请求头里没有,则每次都会返回最新的资源200
缓存判断流程
为了确保html每次都是最新的,我们这里不能使用强缓存。可以在服务器(nginx、tomact)设置访问html文件时Cache-Control为no-cache
。(这个需要在服务器配合设置,前端是处理不了的)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。