手摸手教你解决重定向缓存问题
问题产生:
测试粑粑:测试环境已经搭好了,前端打个包吧!
weber:好嘞!快速输入命令:npm run build:stagging
三分钟后……
测试粑粑:是不是打错包了?怎么还没变?
weber:刷新下页面试试!
测试粑粑:没用鸭~
weber:蛤~清理下浏览器缓存!
测试粑粑:出来了,**牛皮鸭!!!
问题到这里,我陷入了沉思,咋回事呢,如果每次发布需要用户手动清除浏览器缓存,这无疑是一个巨大的bug?于是开始列出了问题排查清单:
1、刷新页面重新进行了doc【index.html】请求,无效;而清理浏览器缓存缺生效了,说明浏览器缓存了文件导致刷新请求时还是之前的文件。
2、webpack打包时,output给js、css加上了hash,那js、css应该就不会缓存。
开始排查
一、检查了webpack打包配置:
module.exports = {
context : path.join(__dirname,'src'),
entry:{
main: './index.js',
vender:['./jquery.js','./test.js']
},
module:{
rules:[{
test:/\.css$/,
use: extractTextPlugin.extract({
fallback:'style-loader',
use:'css-loader'
})
}]
},
output:{
path:path.join(__dirname, '/dist/js'),
filename: 'bundle.[name].[hash].js',
},
plugins:[
new extractTextPlugin('../css/bundle.[name].[hash].css')
]
}
发现webpack打包没有问题。
index.html是304请求,那说明index.html被缓存了。
解决问题
开始寻找解决办法,方法有很多,有前端配置的,也有后端配置的。
考虑到webpack打包生成的html只是作为引入js、css的容器,若只是不缓存html文件,代价其实很小。选择如下方法:
1、在html head头部添加不缓存html配置:
注:meta是tml语言head区的一个辅助性标签,其中的http-equiv字段定义了服务器和用户代理的一些行为。在之前的规范中,meta的http-equiv字段中有以下值与http header缓存相关的字段功能类似
<head>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
若采用这种方式,请在public文件加下的index.html配置。
2、修改nginx.conf,增加add_header Cache-Control 'no-cache, no-store, must-revalidate'不缓存html配置:
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location ~* \.(gif|jpg|jpeg|png|css|js|ico|eot|otf|fon|font|ttf|ttc|woff|woff2)$ {
expires 1M;
add_header Cache-Control "public";
}
location / {
add_header Cache-Control 'no-cache, no-store, must-revalidate';
}
error_page 404 /index.html;
}
其实这两个配置都是在请求head加上不缓存html的配置,一个在前端,一个在运维。翻阅w3c文档发现,但现在w3c的规范字段中这些值已经被移除,一个很好的理由是:
Putting caching instructions into meta tags is not a good idea, because although browsers may read them, proxies won't. For that reason, they are invalid and you should send caching instructions as real HTTP headers.
综合之后还是第二种方案较为完善。
bug再现:
weber:这次修改了nginx配置,这次打包应该不会出现上次的缓存问题了,不用手动清楚浏览器缓存了!
测试粑粑:牛皮鸭,我试试~
weber:(自信的小表情,期待的小红手)~
测试粑粑:还是有问题鸭!还是没更新过来!
weber:你是直接请求是吧?有没有刷新页面?
测试粑粑:没有,直接请求的~
weber:好了,我知道了!
问题到这里,又出现了bug。如果直接请求网址,是会请求到最新的html文件,但是还会存在用户不刷新直接请求的情况。
理清思路:
其实到这一步问题已经很清晰了,重新理一遍webpack打包过程、浏览器缓存策略,问题就很容易解决了。
一、webpack打包:
public/index.html:文件是一个会被 html-webpack-plugin 处理的模板。在构建过程中,资源链接会被自动注入。另外,Vue CLI 也会自动注入 resource hint (preload/prefetch、manifest 和图标链接 (当用到 PWA 插件时) 以及构建过程中处理的 JavaScript 和 CSS 文件的资源链接。ouput里面的文件都会inject
二、HTTP重定向:
服务器的nginx配置如下:假若输入:https://example.com,https://example.com/a都会定位到root下的index.html文件,也会触发请求html文件。
三、浏览器缓存:
再次查看增加了不缓存html文件,请求状态变成了200。
因此,在不刷新浏览器的情况下请求,html是没有被请求的,仍然是第一次输入网址请求回来的html文件,里面的js、css也是之前的,所以浏览器不会再去请求js、css文件。解决办法:
在axios请求加上版本号,如果版本号对应不上,则返回code,让前端去与用户交互是否已经更新了,需要刷新页面。
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: 唱跳rap和web 原文链接:https://juejin.im/post/6844904041802104845