导读
很长时间以来,项目一直设置为缓存所有的文件,因此遇到一个代码版本更新浏览器刷新失效的问题。通常,我们打包时(采用webpack方案)输出时会采用contentHash来保证更新代码后相关的js、css文件发生变更。但我们可能忽略了一个问题:js、css文件名发生改变浏览器就一定会加载吗?答案当然是否定的,让我们研究下如何解决。
知识提示
❝为了更好地理解一下文章,你需要了解以下知识;如已了解可跳过。
❞
使用contentHash
我们使用webpack打包经常看到我们打包的chunk文件除了文件名还有一串乱七八糟的字母,例如:
![webpack输出文件时混入hash](https://i-blog.csdnimg.cn/blog_migrate/6de0d7eb8b0204ffbf9f72873572dae3.png)
这就是webpack帮助我们混入的一些hash值,以实现我们的chunk充分利用浏览器的缓存功能,但是有时候每次打包可能所有的hash就将重新计算,也就是我们的资源文件名全部被改变了,文件名都变了浏览器还怎么缓存呢?于是,contentHash
就闪亮登场了。顾名思义,contentHash
是根据内容做的hash,也就是当我们的代码改变时,相关的js、css的hash才会变化,那么,浏览器通过请求发现这几个文件在缓存中不存在,就会向服务器请求资源而不是从本地缓存中读取了;而其它没有发生变动的文件自然还是从缓存读取,这样页面加载时间就非常地短了。
页面刷新一定就加载吗?
上述的问题说完后,我们考虑一下:每次版本更新contentHash
确实为我们的cjs、css生成了与上次版本不一样的文件名,并由webpack将这些文件自动注入到我们的index.html中。问题来了,index.html事实上也是被缓存的,我们两次版本事实上都是同一个index.html,那么两次被加载的chunk文件名并没有发生变化。 假设原来的版本1.0的一个chunk文件名是:<chunk-4cb2a638.22e8ca85.js> 版本2.0是<chunk-4af2a696.22e8ca85.js>,那么版本1的文件已经被缓存了,版本2肯定因为没有发生过请求没被缓存,但index.html也被缓存,那么这时(版本2.0发布后)刷新浏览器我们会发现我们的修改居然没生效!这时,我们作为开发者,很容易就会想到去清除浏览器的缓存,但是用户不答应啊,用户未必懂得,所以作者之前没少被用户直接找上门狠狠吐槽。因此,我们不能让index.html被浏览器缓存,以保证每次刷新都会去重新请求服务端拿到最新的index.html。这样,版本更新后,浏览器总能发现我们的相关css、js文件发生了变动,就会重新请求,而文件名未发生改变的资源自然从缓存中获取。 那么,我们如何不缓存index.html呢,有两个方法:
html在meta设置不缓存
<meta http-equiv="pragma" content="no-cache">
nginx配置
由于现在大多都采用了前端框架完成开发,因此部署时大多都是SPA的应用,当然MPA也有很多,那么我们只要让nginx告诉浏览器我们不需要对html文件使用缓存就好了,具体的配置如下:
server {
listen 80;
server_name test.exmaple.cn;
location / {
if ($request_filename ~* .*\.(?:htm|html)$) ## 配置页面不缓存html和htm结尾的文件
{
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
}
root /web/;
index index.html;
try_files $uri $uri/ /index.html =404;
}
}
总结
以上就是如何使我们的生产项目版本能及时通过简单的刷新就能加载完毕的全部内容了,有其它问题或者文字描述错误欢迎评论区补充。
最后,欢迎大家到我的github上给我一些star。
其它参考资料
-
nginx配置不缓存html -
浏览器缓存机制概览
![强制缓存和协商缓存](https://i-blog.csdnimg.cn/blog_migrate/352ff67224c4808b993b32049c56191f.png)
本文由 mdnice 多平台发布