Vite 报错找不到 @vitejs/plugin-react:两种成因与对应修复
译注:本文译自 dev.to 文章《Fix Cannot find module '@vitejs/plugin-react' in Vite》,作者 Mahdi Benrhouma,原文发布于 2026-09-27。原文链接见文末。文中涉及的版本号、命令与配置均按原文保留。
在 vite.config.ts 中出现 Cannot find module '@vitejs/plugin-react' or its corresponding type declarations(TS2307)报错,通常有两种截然不同的成因。若包本身缺失,或编辑器的 TypeScript 服务仍持有旧视图,安装依赖并重启 TS 服务即可;若 tsc 额外输出 There are types at … but this result could not be resolved under your current 'moduleResolution' setting,则说明包已安装,但 tsconfig.node.json 仍在使用 "moduleResolution": "Node",该模式会忽略 package.json 的 exports 字段。在较新的 TypeScript 上将其改为 "bundler" 即可解决。
报错现场
这个问题最初由一位使用 npm create vite@latest 脚手架创建 React + TypeScript 项目的开发者在 Stack Overflow 上提出。npm run dev 运行正常且无警告,但 VS Code 却在 vite.config.ts 的第一行 import 下画了波浪线。对配置文件所属项目运行编译器,会得到同样的文本报错:
vite.config.ts(1,19): error TS2307: Cannot find module '@vitejs/plugin-react' or its corresponding type declarations.紧随其后的第二行(如果有)才是判断成因的关键,因此在动手修改前应先读它。
为什么会发生
有两个独立的程序会读取 vite.config.ts。Vite 负责加载并运行它,而 Vite 官方特性文档明确指出:「Vite 只对 .ts 文件做转译,不做类型检查。」真正做类型检查的是编辑器的 TypeScript 语言服务,它使用包含该文件的 tsconfig 中的编译选项。这正是应用能启动、编辑器却报错的原因:运行时与类型检查器各自独立解析 import。
在当前 create-vite 项目中,根 tsconfig.json 的 "files": [] 只引用其他配置;旧版本项目则自带 compilerOptions 和 "include": ["src"]。无论哪种情况,真正管辖 vite.config.ts 的都是 tsconfig.node.json,其 include 为 ["vite.config.ts"]。修改根文件或 tsconfig.app.json 并不能单独消除该错误。
成因 A——包不存在,或编辑器尚未感知。 create-vite 会询问 Install with npm and start now?,若选择拒绝,它只打印安装命令。在 npm install 完成前用 VS Code 打开文件夹,就会产生没有第二行的 TS2307。当 import 指向的包不在 devDependencies 中时也一样,例如项目装的是 @vitejs/plugin-react,代码却引用了 @vitejs/plugin-react-swc,反之亦然。Stack Overflow 上被采纳的答案就是重启 VS Code,另一个答案则只重启 TypeScript 服务——两者都适用于「包在编辑器解析 import 之后才落盘」的情形。
成因 B——包只通过 exports 暴露类型。 TypeScript 模块参考文档指出,package.json 的 "exports" 在 node10(旧称 node)下不受支持,在 bundler 下受支持。当插件更改其清单文件后,这就成了问题。npm registry 显示,@vitejs/plugin-react 4.7.0 仍声明 main 和 types,而 5.0.0 只声明 exports,4.7.0 是 4.x 的最后一个版本。与此同时,旧版 create-vite 生成的项目保留了旧设置:create-vite 4.0.0 的 tsconfig.node.json 设置 "moduleResolution": "Node",其 package.json 将 typescript 锁定为 ^4.9.3。在这类项目中把插件升级到 5.x 或更高,TypeScript 就再也找不到 dist/index.d.ts,尽管它就在 node_modules 里。
同样的情况也适用于 Vite 8 起的 vite 本身:vite 7.1.0 的清单有 main 和 types,vite 8.0.0 两者皆无。在 Vite 4 到 7 上配合升级后的插件,只有插件那一行 import 失败;在 Vite 8 上,vite.config.ts 的两行都会失败。
区分两种成因
用管辖该文件的配置直接询问编译器:
npx tsc -p tsconfig.node.json --noEmit在 TypeScript 5.9.3、@vitejs/plugin-react 6.1.1 与 Vite 8.3.1、"moduleResolution": "Node" 的复现环境下,输出会带有标志性提示(路径已缩短):
vite.config.ts(1,19): error TS2307: Cannot find module '@vitejs/plugin-react' or its corresponding type declarations.
There are types at '/app/node_modules/@vitejs/plugin-react/dist/index.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'.
vite.config.ts(2,30): error TS2307: Cannot find module 'vite' or its corresponding type declarations.
There are types at '/app/node_modules/vite/dist/node/index.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'.若 bundler 设置正确、但 import 的包未安装,报错则单独出现:
vite.config.ts(1,19): error TS2307: Cannot find module '@vitejs/plugin-react-swc' or its corresponding type declarations.没有提示即成因 A,有提示即成因 B。
成因 A 的修复:装对包,再重启 TS 服务
- 检查项目实际安装了哪个 React 插件:
npm ls @vitejs/plugin-react @vitejs/plugin-react-swc- 若
vite.config.ts引用的那个缺失,安装它,或把 import 改成已安装的那个。默认插件:
npm install --save-dev @vitejs/plugin-reactSWC 变体按 plugin-react-swc README 用 npm i -D @vitejs/plugin-react-swc 安装,并如下引用:
import react from '@vitejs/plugin-react-swc'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [react()],
})- 重启语言服务以重新解析 import:打开命令面板(
Ctrl+Shift+P,macOS 为Cmd+Shift+P),运行TypeScript: Restart TS server。重启整个编辑器效果相同。
成因 B 的修复:把 tsconfig.node.json 切到 bundler 解析
- 升级 TypeScript。
bundler模式自 TypeScript 5.0 引入,旧模板的^4.9.3无法使用。测试中,TypeScript 5.0.4 也无法解析@vitejs/plugin-react6.1.1 的声明文件,而 5.9.3 与 6.0.3 可正常编译。对旧项目而言干扰最小的选择是 TypeScript 5.9:
npm install --save-dev typescript@~5.9.3若改用 TypeScript 6(typescript@~6.0.2,当前模板使用的范围),旧模板的根 tsconfig.json 也会出问题:它同样设置了 "moduleResolution": "Node" 和 "esModuleInterop": false,测试中 TypeScript 6.0.3 以 TS5107 拒绝了这两项。此时需在根 tsconfig.json(或 tsconfig.app.json)中也设置 "moduleResolution": "bundler",并删除 "esModuleInterop": false 一行;做这两处修改后,同一文件即可无错编译。
- 用能读取
exports的版本替换tsconfig.node.json。以下配置保留了旧模板的composite标志,使根tsconfig.json中的项目引用仍可用,并新增target与skipLibCheck:缺少它们时,TypeScript 5.9.3 上的复现会在 Vite 8 从 Rolldown 引入的声明文件中报 TS18028(「Private identifiers are only available when targeting ECMAScript 2015 and higher」)。
{
"compilerOptions": {
"composite": true,
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"skipLibCheck": true
},
"include": ["vite.config.ts"]
}若想与全新生成的项目保持一致,当前模板省略
moduleResolution,改为设置"module": "nodenext"。两种模式都能读取exports;编译器自身的提示列出node16、nodenext和bundler为可用设置。确保编辑器使用项目自带的 TypeScript,而非 VS Code 内置版本。VS Code 的 TypeScript 文档指出,工作区版本独立于 VS Code 随附版本,可通过
TypeScript: Select TypeScript Version命令切换,或用js/ts.tsdk.path工作区设置固定。随后按成因 A 的方式重启 TS 服务。
验证修复
运行与之前相同的命令:
npx tsc -p tsconfig.node.json --noEmit它必须无输出退出。在上述复现中,第 2 步的 bundler 配置在 TypeScript 5.9.3 与 6.0.3 上均通过。然后打开 vite.config.ts,TS 服务重启后波浪线应消失。最后确保流水线也运行同样的检查,而不只是编辑器。当前模板的构建脚本是 tsc -b && vite build,-b 会构建被引用的 tsconfig.node.json。旧模板的脚本是 tsc && vite build:裸 tsc 只编译根项目,它包含 src 而不含 vite.config.ts,因此构建通过并不能证明该错误已解决。在这类项目中,可把显式检查加入脚本,例如 "build": "tsc && tsc -p tsconfig.node.json --noEmit && vite build",或在 CI 中运行该命令。
TypeScript 6 改变了你看到的第一个错误
在 TypeScript 6 上,旧的 "moduleResolution": "Node" 不再走到 TS2307,编译器会更早停在配置层:
error TS5107: Option 'moduleResolution=node10' is deprecated and will stop functioning in TypeScript 7.0. Specify compilerOption '"ignoreDeprecations": "6.0"' to silence this error.TypeScript 6.0 公告建议:直接面向 Node.js 时迁移到 nodenext,使用打包器时迁移到 bundler。添加 "ignoreDeprecations": "6.0" 在这里并非修复:测试中它压下了 TS5107,TS2307 随即回归,并带有同样的 There are types at … 提示,因为解析仍然忽略 exports。
相似但不同的报错
TS2307 表示模块完全无法解析。TS7016「Could not find a declaration file for module」是另一种情况:JavaScript 能解析但没有类型,解法是 @types 包或本地声明。若 import 能解析但缺少某个具体名称,包的 exports 映射同样是常见元凶。而当找不到文件的是 Vite 构建而非编辑器时,问题出在 Rollup 的解析而非 TypeScript。
这些报错背后的模式一致:某个工具用与安装时不同的规则去解析 import。对 vite.config.ts 而言,规则存放在 tsconfig.node.json 中;一个升级了依赖却没升级该文件的项目,会持续报告一个明明就在磁盘上的模块,直到其解析模式跟上包发布类型的新方式。