强缓存:
cache-control常见的值有max-age public private no-cache no-store等
如上图设置了cache-control的值为 max-age=0, private, must-revalidate
max-age表示缓存的时间,
private 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它),私有缓存可以缓存响应内容。
must-revalidate表示告诉浏览器、缓存服务器,本地副本过期前,可以使用本地副本;本地副本一旦过期,必须去源服务器进行有效性校验
Cache-Control 常见字段的含义:
public
表明响应可以被任何对象(包括:发送请求的客户端,CDN 等代理服务器,等等)缓存,即使是通常不可缓存的内容(例如,该响应没有max-age指令或Expires消息头)。
private
表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它),私有缓存可以缓存响应内容。
no-cache
可以在本地进行缓存,但每次发请求时,都要向服务器进行验证,如果服务器允许,才能使用本地缓存(即:需要协商缓存)。
no-store
禁止缓存客户端请求或服务器响应的内容,每次都须重新请求服务器拿内容。
max-age
设置缓存存储的最大周期,超过这个时间缓存被视为过期 (单位:秒)。
must-revalidate
在缓存过期前可以使用,过期后必须向服务器验证。
具体的时候是会好几个值一起搭配使用的。就像上面的截图里一样。
而在谷歌浏览器中,经常会看到
Disk Cache
缓存资源在硬盘中,浏览器(或页面标签)关闭后硬盘中的缓存不会消失,下次进入页面还能从硬盘中获取。
Memory Cache
缓存资源在内存中,浏览器(或页面标签)关闭后内存中的缓存就会被释放,重新打开页面取不到该缓存。
协商缓存:
上面说到的强缓存就是给资源设置个过期时间,客户端每次请求资源时都会看是否过期;只有在过期才会去询问服务器。所以,强缓存就是为了给客户端自给自足用的。而当某天,客户端请求该资源时发现其过期了,这是就会去请求服务器了,而这时候去请求服务器的这过程就可以设置协商缓存。这时候,协商缓存就是需要客户端和服务器两端进行交互的。
整个步骤可以分为:
1.资源未过期
发请求-->看资源是否过期-->过期-->请求服务器-->服务器对比资源是否真的过期-->没过期-->返回304状态码-->客户端用缓存的老资源。
2.资源过期
发请求-->看资源是否过期-->过期-->请求服务器-->服务器对比资源是否真的过期-->过期-->返回200状态码-->客户端如第一次接收该资源一样,记下它的cache-control中的max-age、etag、last-modified等。
总结:
强缓存就是服务端控制缓存的类型时间等等,客户端请求资源时按照服务端设置的内容去请求。协商缓存就是客户端发起请求后,由服务端告知是否取缓存里的数据。如果资源真的过期,服务端会返回200,客户端就真是请求数据。如果资源没过期,服务端会返回304,告知客户端,可以去取缓存里的数据。总结为请求资源时,把用户本地该资源的 etag 同时带到服务端,服务端和最新资源做对比。
如果资源没更改,返回304,浏览器读取本地缓存。
如果资源有更改,返回200,返回最新的资源。(etag就是一串唯一标识,如果更改,则说明资源文件内容变了,如果不更改则说明没变。)
在日常工作中。重新打包部署后,肯定会出现浏览器缓存的问题,导致用户手里第一时间展示的不是最新代码。这个时候就需要我们去给每个打包出来的文件设置个唯一标识。每次重新打包都生成不一样的标识,来告知浏览器。资源更新了,不要再拿缓存里的了。
具体步骤如下
1.在build文件夹下的webpack.prod.conf.js添加:
const version = new Date().getTime(); //声明一个时间戳的命名,保证唯一性
2.将output配置的js修改文件名,改成如下:
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].' + version + '.js'), //添加声明的变量
chunkFilename: utils.assetsPath('js/[id].[chunkhash].' + version + '.js') //添加声明的变量
},
3.将css的文件名修改成如下:
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].' + version + '.css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
保存后直接npm run build
每一个文件都加上了与历史版本不同且唯一性的文件名,浏览器加载资源的时候就会重新获取资源,从而解决前端资源缓存的问题
借鉴:
https://blog.csdn.net/weixin_43829905/article/details/115467745
https://www.jianshu.com/p/9c95db596df5