为什么我的 Vue 项目静态资源没走 Disk Cache?
我用 Vue CLI 打包上线后,发现每次刷新页面都会重新请求 JS 和 CSS 文件,明明设置了 long-term caching,但 Chrome DevTools 里看到这些资源的状态是 200(from memory cache)或者直接重新下载,根本没进 Disk Cache。是我配置错了吗?
我试过在 vue.config.js 里加 filenameHashing: true,也确认了服务器返回了 Cache-Control: max-age=31536000,但还是不行。本地开发时没问题,一上生产环境就不缓存。
<template>
<div id="app">
<img src="./assets/logo.png" alt="logo" />
<HelloWorld />
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
components: { HelloWorld }
}
</script>
首先得确认你的静态资源的缓存策略确实生效了。虽然你设置了 filenameHashing: true 和服务器返回了 Cache-Control: max-age=31536000,但这些还不够。具体来说,Chrome 的 Disk Cache 机制比较复杂,有时候会因为一些小细节导致缓存失效。
你需要检查几点:
一、确保你的文件名 hash 真正起作用了。打开生产环境下的 index.html,看看引用的 JS 和 CSS 文件名是不是包含了正确的 hash 值。比如:
app.abc123.js这样的格式。如果没生效的话,在 vue.config.js 里这样配置:二、服务器配置也很关键。虽然你说了 Cache-Control 设置对了,但还得检查 ETag 头是否正确设置。ETag 可能会影响缓存行为。你可以用 nginx 的配置来控制:
三、关于 Chrome DevTools 显示的状态。从 memory cache 和 disk cache 都可能显示为 200,但表现不同。memory cache 主要用于较小的资源或者当前页面加载时已经读取过的资源。如果你发现大文件总是从 memory cache 而不是 disk cache 加载,可能是内存缓存优先级的问题。
最后提醒一下,有时开发工具本身也会影响缓存的表现,特别是你在调试模式下。建议在正式排查前清理一下浏览器缓存数据,重启几次看看效果。
说真的,缓存这东西有时挺让人头疼的,尤其是在生产环境中遇到问题时。不过按照上面的步骤仔细排查,应该能找到问题所在。
你看到 from memory cache 是正常的,Chrome 读取资源时优先走内存,刷新页面基本都这样。你需要确认的是:关闭浏览器标签页,等几秒,再重新打开页面,这时候如果还是重新下载,那才是真的没进 Disk Cache。
先拿 curl 查一下服务器实际返回的响应头:
重点看这几项:
服务器返回的必须是类似这样的:
如果同时返回了这些,那就完蛋:
Vary: Cookie 这个坑很多人踩过,服务器只要加了这个,浏览器就认为每个用户的缓存不一样,不会走 Disk Cache。
检查一下你的服务器配置(nginx/apache/cdn),把无关的缓存头删掉,只保留 max-age 就够了。
如果用的是 nginx,加一行:
代码放这了,自己对比一下服务器实际返回的是什么。