Vite 构建报错 Rollup 无法解析 /src/main.tsx 的修复方法
译注:本文翻译自 dev.to 文章《Fix Rollup failed to resolve import "/src/main.tsx" in Vite》,作者 Mahdi Benrhouma,原文发布于 2026-09-24。原文链接见文末。
如果你正把一个 React 应用从 Webpack 迁移到 Vite,构建时却报出 [vite]: Rollup failed to resolve import "/src/main.tsx",问题几乎总是出在 index.html 相对于 vite.config.ts 中 root 配置的位置上。修复方式是把 index.html 移回项目根目录,并删除自定义的 root 选项。这个报错在 Stack Overflow 上一个热门问题中被报告过,同样是 Webpack 迁移 Vite 时产生的相同诊断信息。
要点如下:
- 症状:执行
vite build时出现[vite]: Rollup failed to resolve import "/src/main.tsx"。 - 根因:
index.html被放在自定义的root目录(例如src/)内,而其中的 script 标签使用了从项目级目录出发的绝对路径,而非从配置的 root 出发。 - 修复:把
index.html移到项目根目录,并从vite.config.ts中删除root属性。 - 验证:运行
npm run build,构建不再出现解析错误。
错误信息解读
终端中看到的完整输出大致如下:
> tsc && vite build
vite v4.3.5 building for production...
✓ 2 modules transformed.
✓ built in 32ms
[vite]: Rollup failed to resolve import "/src/main.tsx" from "/Users/John/source/reddwarf/frontend/snap-web/src/index.html".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
error during build:
Error: [vite]: Rollup failed to resolve import "/src/main.tsx" from "/Users/John/source/reddwarf/frontend/snap-web/src/index.html".
at viteWarn (...)
at onwarn (...)
at onRollupWarning (...)
...这个错误只在执行 vite build 时出现。开发服务器(vite dev)通常不会复现该错误,因为它的模块解析更宽松——它能解析一些生产环境 Rollup 构建会拒绝的路径。这是很多开发者习惯用 vite dev 测试一切、直到构建时才撞上解析失败的常见坑。
错误信息建议把该导入加入 build.rollupOptions.external。不要这么做。 把自己的入口模块外部化会把它从产物中剥离,导致运行时失败——这个建议只是通用兜底提示,并非针对此结构性问题的真正修复方案。
为什么 Vite 无法解析该导入
Vite 使用 vite.config.ts 中的 root 属性来确定项目的起点。默认 root 是你运行 vite 命令的目录,通常是项目根目录(my-app/)。在默认的 Vite 脚手架中,index.html 就位于此处,内容包含:
<script type="module" src="/src/main.tsx"></script>路径 /src/main.tsx 是从项目根目录出发的绝对路径——既不相对于 HTML 文件,也不相对于配置的 root。它的含义是:“从 Vite 所见的文件系统根出发,进入 src/main.tsx。”
在出错的配置中,开发者把 index.html 移到了 src/ 内部,并在 vite.config.ts 中设置了 root: path.join(__dirname, 'src')。其意图是模仿 Webpack 中入口 HTML 位于 src 内的结构。但此时 Vite 的 root 变成了 src,而 script 标签仍然写着 /src/main.tsx。对 Vite 来说,这意味着“从 root(即 src/)出发,再进入 src/main.tsx”——于是它会去找 <project>/src/src/main.tsx。该文件不存在,Rollup 便抛出解析错误。
有问题的配置如下:
// vite.config.ts — 出错的版本
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
root: path.join(__dirname, 'src'), // <— root 变成 <project>/src
plugins: [react()],
build: {
outDir: "build"
}
});在该 root 下,script 标签中的 /src/main.tsx 会尝试解析为 <project>/src/src/main.tsx,构建随即失败。
修复:恢复默认文件结构
最直接的修复方式——也是 Vite 官方文档所期望的——是把 index.html 移回项目根目录,并删除自定义的 root 属性。
移动文件前,先检查当前目录结构。在项目目录下运行 tree -L 2(macOS 上如未安装可通过 brew install tree 安装)。出错的结构如下:
.
├── node_modules
├── package.json
├── src
│ ├── App.tsx
│ ├── main.tsx
│ ├── index.html # <— index.html 在 src 内
│ └── vite-env.d.ts
├── tsconfig.json
└── vite.config.ts # 包含 root: 'src'src 内的 index.html 可能用绝对路径引用入口,例如 <script type="module" src="/src/main.tsx"></script>。该路径本应相对于项目根目录(即包含 vite.config.ts 的目录),但在 root 设为 src 后,它变成了 src\src\main.tsx,从而引发失败。
把 index.html 移到项目根目录:
mv src/index.html index.html此时目录结构应变为:
.
├── index.html # <— 现在位于项目根目录
├── node_modules
├── package.json
├── src
│ ├── App.tsx
│ ├── main.tsx
│ └── vite-env.d.ts
├── tsconfig.json
└── vite.config.ts # 无 root 属性index.html 现在与 vite.config.ts 相邻。Vite 会自动把包含 vite.config.ts 的目录视为 root,因此绝对路径 /src/main.tsx 能正确解析为 <project>/src/main.tsx。
有些开发者尝试一种不移动 index.html 的变通方案:保留 root: 'src',把 script 标签改为 "./main.tsx"(相对于 HTML 文件)。这样 Vite 能解析文件,因为 root 是 src,而 ./main.tsx 正确指向 src/main.tsx。虽然这能消除解析错误,却引入了脆弱性。Vite 文档强烈建议把 index.html 保留在项目根目录。把它移入子目录并改用相对路径,可能破坏其他仍依赖根目录绝对路径的资源导入(如 favicon 或静态文件)。请坚持推荐布局:index.html 位于项目根目录,配置中不设自定义 root。
修复后的配置文件:
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
outDir: "build" // 保留你想要的输出目录
}
});注意 root 属性已被完全移除。在此设置下,vite build 会相对于项目目录解析 /src/main.tsx,正如预期。
验证构建
移动 index.html 并删除 root 属性后,重新运行构建:
npm run build成功的构建会输出类似内容:
vite v4.3.5 building for production...
✓ 32 modules transformed.
build/index.html 0.46 kB
build/assets/index-abc123.js 145.32 kB │ gzip: 48.76 kB
build/assets/index-abc123.css 0.87 kB │ gzip: 0.44 kB
✓ built in 1.23s不再有 Rollup 解析错误。HTML、JavaScript 和 CSS 被写入 build/ 目录(或你设置的 build.outDir)。打开 build/index.html,确认 <script> 标签指向带哈希的资源文件。该文件就是你打包后的应用入口。
如果仍然看到相同的解析错误,用 ls 再次确认文件位置:
ls -l src/main.tsx # 应当存在
ls -l index.html # 必须位于项目根目录同时检查 vite.config.ts,确保没有残留的 root 属性。遗留的 root: 'src' 会让错误在移动文件后再次出现,因为 Vite 会再次从 src/ 出发解析绝对路径 /src/main.tsx。
如果构建因其他原因失败——例如 TypeScript 类型错误或缺少依赖——请单独处理。解析错误应当已经消失。若它仍然存在,请检查 package.json 的构建脚本是否覆盖了配置,或通过 CLI 标志(如 vite build --root src)传入了显式 root。那会重新引入该问题。
IDE 配置
如果你使用 WebStorm 或 IntelliJ IDEA,IDE 中配置的 Node.js 解释器可能掩盖或放大构建问题。在 Stack Overflow 的案例中,开发者为项目设置了过时的 Node 14 解释器,而 nvm 实际使用的是 Node 18。这种不匹配导致 ESLint 和 TypeScript 服务报出无关错误,例如:
Error: Cannot find module 'eslint-plugin-react'
Error: Cannot find module 'typescript'这些错误与 Rollup 失败一起出现在 IDE 终端和工具窗口中,使真正的问题更难定位。
在 IDE 之外确认当前 Node 版本:
node -v # 例如 v18.17.1
which node # 例如 /Users/yourname/.nvm/versions/node/v18.17.1/bin/node在 WebStorm 中打开 Settings → Languages & Frameworks → Node.js。在 Node interpreter 字段中点击浏览按钮,选择 which node 报告的路径。或者,如果你使用 nvm,可以选择 .nvm 目录下的解释器。应用更改并重启 ESLint/TypeScript 服务(更改解释器后通常会自动重启)。那些虚假的模块未找到错误应当消失。
一旦 IDE 解释器与 CLI 版本一致,运行 vite build 时你唯一会看到的错误就是 Rollup 解析失败。修复它(移动 index.html)之后,IDE 内的构建也能顺利成功。
常见问题
为什么错误只在 vite build 时出现,而 vite dev 不会?
Vite 的开发服务器使用 esbuild 的解析逻辑,比 Rollup 更宽容,有时能解析技术上不正确的路径。而生产构建使用 Rollup 打包并执行严格解析——此时不匹配才会变成硬错误。
是否应该按错误提示把模块加入 build.rollupOptions.external?
不应该。外部化的元素不会被打包,而是期望在运行时提供(例如全局变量)。把 "/src/main.tsx" 加入 external 会让构建完成,但产物会缺失应用入口,在浏览器中崩溃。
相关阅读
- Fix ESLint 'import/extensions' Definition Not Found
- Fix 'originalKeywordKind' DeprecationError in TypeScript
- Fix: compilerOptions.paths Must Not Be Set (Alias Imports)
原文最初发布于 https://www.iloveblogs.blog