Skip to content

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,构建不再出现解析错误。

错误信息解读 ​

终端中看到的完整输出大致如下:

plaintext
> 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 就位于此处,内容包含:

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 便抛出解析错误。

有问题的配置如下:

typescript
// 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 安装)。出错的结构如下:

shell
.
├── 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 移到项目根目录:

shell
mv src/index.html index.html

此时目录结构应变为:

shell
.
├── 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。

修复后的配置文件:

typescript
// 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 属性后,重新运行构建:

shell
npm run build

成功的构建会输出类似内容:

plaintext
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 再次确认文件位置:

shell
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 服务报出无关错误,例如:

plaintext
Error: Cannot find module 'eslint-plugin-react'
Error: Cannot find module 'typescript'

这些错误与 Rollup 失败一起出现在 IDE 终端和工具窗口中,使真正的问题更难定位。

在 IDE 之外确认当前 Node 版本:

shell
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 会让构建完成,但产物会缺失应用入口,在浏览器中崩溃。

相关阅读 ​

原文最初发布于 https://www.iloveblogs.blog

原文链接 ​