vite 的 hmr 默认重置组件状态,但通过 import.meta.hot api 与框架插件(如 @vitejs/plugin-react)可实现状态保持:react 中自动保留 usestate、useref 等值并就地更新;vue/svelte 插件也分别支持响应式状态维持;手动模块需用 hot.dispose 和 hot.data 管理状态。

Vite 的热更新(HMR)默认不会保持组件或模块的状态,比如 React 函数组件的局部变量、useState 的值、useRef 的引用内容,在 HMR 触发时会被重置。但 Vite 提供了标准机制让你主动控制状态是否保留,核心是通过 import.meta.hot API 配合框架适配器(如 @vitejs/plugin-react)来实现“状态保持”。
React 场景下:依赖 @vitejs/plugin-react 自动处理
使用官方 React 插件时,它已内置对 React Refresh 的支持,会自动:
- 在函数组件更新时,尽可能保留
useState、useReducer、useRef和useContext中的值 - 跳过组件完全卸载/重建,改为“就地更新”(patch)其内部状态和闭包
- 对 class 组件则触发强制重新挂载(不保持实例状态)
✅ 前提:确保项目中已正确安装并启用插件:
npm install @vitejs/plugin-react --save-dev
并在 vite.config.js 中配置:
import { defineConfig } from 'vite'<br>import react from '@vitejs/plugin-react'<br><br>export default defineConfig({<br> plugins: [react()]<br>})
自定义模块状态保持(通用 JS 模块)
对于非 React 的普通模块(如工具函数、配置对象、全局 store),你可以手动用 import.meta.hot 管理状态生命周期:
- 在模块首次加载时初始化状态(如缓存对象、计数器)
- 监听
hot.accept,在更新前将关键数据保存到hot.data - 在
hot.dispose中清理副作用(如定时器、事件监听) - 在新模块加载后,从
hot.data恢复状态
示例:
// counter.js<br>let count = 0<br><br>if (import.meta.hot) {<br> // 更新前保存当前值<br> import.meta.hot.dispose((data) => {<br> data.count = count<br> })<br><br> // 模块被替换后恢复状态<br> if (import.meta.hot.data.count !== undefined) {<br> count = import.meta.hot.data.count<br> }<br>}<br><br>export function increment() { return ++count }
Vue / Svelte 等框架的状态保持逻辑
Vue(使用 @vitejs/plugin-vue)和 Svelte(@sveltejs/vite-plugin-svelte)也各自封装了 HMR 行为:
- Vue 单文件组件(SFC)中,
data()返回的对象、ref/reactive响应式状态均被自动保留 - Svelte 组件中,
let声明的响应式变量、$:声明的派生值也会在 HMR 中维持 - 所有框架都依赖插件对编译产物做 HMR 注入,因此务必使用对应官方插件而非裸写 HMR 逻辑
为什么有时状态还是丢了?常见原因
状态未保持通常不是 Vite 问题,而是以下情况导致:
- 组件被写成无状态函数(没有 hooks 或响应式声明),每次 HMR 都执行全新函数体
- 手动调用了
hot.invalidate()或配置了hot.accept(false) - 模块导出方式不符合框架插件预期(如 React 插件要求默认导出 JSX 元素)
- 启用了
esbuild作为 JSX 转换器(而非插件内置的 Babel/React Refresh) - 使用了非标准构建流程(如绕过插件直接写
import.meta.hot.accept但未处理 data 同步)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











