3、Vite缓存策略:依赖预构建缓存、浏览器缓存策略、文件哈希缓存
聊到Vite的缓存,我得先坦白一件事。我刚从Webpack切换到Vite那会儿,总觉得它「偷偷摸摸」干了很多事。尤其是第一次启动时那个 Pre-bundling dependencies 的提示,我一度以为它卡住了。后来才明白,这其实是Vite最聪明的设计之一。
说白了,Vite的缓存策略分三层:依赖预构建缓存、浏览器HTTP缓存、文件哈希缓存。这三层各司其职,又互相配合。我们一层层拆开看。
3.1 依赖预构建缓存:为什么第一次启动那么慢?
你想想看,Vite在开发模式下用的是ES Module。但node_modules里的依赖,很多还是CommonJS格式,或者有大量内部模块引用。浏览器直接加载?不行的。
所以Vite做了个预处理:把依赖统一转换成ES Module,并合并成少量文件。这个过程叫「依赖预构建」。
预构建的结果会缓存到哪里?默认在 node_modules/.vite 目录下。我习惯把这个目录叫做「Vite的私房钱」。
缓存判断依据:
package-lock.json或yarn.lock是否变化vite.config.js中的optimizeDeps配置是否变化- Node.js 版本是否变化
只要这些没变,Vite就不会重新预构建。所以第二次启动时,你会感觉快得像闪电。
我的小技巧: 如果你改了某个依赖的版本,但锁文件没更新(比如直接改了node_modules里的文件),Vite不会自动重新预构建。这时候可以手动删除 node_modules/.vite 目录,或者运行 npx vite --force。我曾经因为这个排查了半天,后来学乖了。
3.2 浏览器缓存策略:304 Not Modified 的秘密
开发模式下,Vite返回的静态资源都带着特殊的HTTP头。我截个关键配置给你看:
// Vite 内部对静态资源的响应头设置
// 对于 JS/TS 模块
Cache-Control: no-cache
// 对于 CSS、图片等静态资源
Cache-Control: max-age=31536000, immutable
为什么JS模块要用 no-cache?因为开发时你随时可能改代码。如果浏览器缓存了旧的JS模块,你改了代码页面却没反应,那得多崩溃。
但CSS和图片就不一样了。这些资源很少在开发时频繁改动,所以Vite允许浏览器缓存一年。嗯,这里要注意:如果改了CSS文件,Vite会通过模块热更新(HMR)直接推送新样式,不需要走HTTP缓存。
我曾经踩过的坑: 有次我在开发环境调试一个图片加载问题,改了图片文件但页面始终显示旧的。查了半天才发现,浏览器缓存了这张图。虽然Vite设置了 immutable,但浏览器还是优先用自己的缓存。解决办法:打开开发者工具,勾选「Disable cache」。
3.3 文件哈希缓存:生产构建的指纹
生产环境就完全不一样了。Vite会把所有静态资源文件名加上哈希值。比如:
// 构建前
src/main.js
src/App.vue
// 构建后
assets/main.a1b2c3d4.js
assets/App.5e6f7g8h.js
这个哈希值是根据文件内容计算出来的。文件内容变了,哈希就变。浏览器发现URL变了,自然会重新请求新文件。
我个人的习惯是,在 vite.config.js 里这样配置:
// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
output: {
// 自定义哈希长度,默认是8位
entryFileNames: 'assets/[name].[hash:8].js',
chunkFileNames: 'assets/[name].[hash:8].js',
assetFileNames: 'assets/[name].[hash:8][extname]'
}
}
}
})
哈希长度8位够用吗?说实话,对于绝大多数项目足够了。哈希碰撞的概率比中彩票还低。
3.4 缓存策略对比表
| 缓存类型 | 作用阶段 | 缓存位置 | 失效条件 |
|---|---|---|---|
| 依赖预构建缓存 | 开发启动 | node_modules/.vite |
锁文件、配置、Node版本变化 |
| 浏览器HTTP缓存 | 开发运行 | 浏览器内存/磁盘 | 响应头 no-cache 或手动禁用 |
| 文件哈希缓存 | 生产构建 | CDN/浏览器 | 文件内容变化导致哈希改变 |
3.5 避坑指南:缓存引发的诡异问题
我遇到过最离谱的一次:同事说他的页面样式不对,我过去一看,他的浏览器里还加载着昨天构建的CSS文件。哈希没变,但内容变了。为什么?因为他在构建时用了 --watch 模式,但没清浏览器缓存。
所以我的建议是:
- 开发时:养成按
Ctrl+Shift+R强制刷新页面的习惯 - 构建时:确保每次构建都生成新的哈希值
- 部署时:CDN的缓存策略要配合文件哈希,设置
immutable头
一个小工具推荐: 我常用 vite-plugin-inspect 这个插件,可以直观看到每个模块的缓存状态。安装后访问 http://localhost:5173/__inspect/,就能看到Vite内部是怎么处理缓存的。
总结一下:Vite的缓存策略说白了就是「该快的时候快,该新的时候新」。开发时依赖预构建缓存让你秒启项目,浏览器缓存配合HMR让你实时看到修改。生产时文件哈希缓存让用户永远拿到最新代码,同时还能利用CDN加速。
嗯,缓存这东西,用好了是神器,用不好就是坑。希望我这十几年的经验能帮你少走些弯路。