router-generator: sibling `physical()` subtrees in a virtual route config generate duplicate identifiers

未关闭 适合新手
#8,879 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

@karlshea 已经在做这个了。

开始于 2026年11月5日。

  • #8880 来自 @karlshea —— 未关闭

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
76/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
typescript, vite

调研方向

阅读 packages/router-generator/src/filesystem/virtual/getRouteNodes.ts,重点关注 getRouteNodesRecursive 的物理分支,以及它如何构建路由变量名。使用链接中的 StackBlitz 复现问题并运行 npm build;当同级物理子树生成不同的导入标识符和路由标识符(例如 AccountsIndexRouteImport 和 BillingIndexRouteImport),且构建成功时,即表示完成。

由索引模型根据 Issue 内容生成。

描述

Which project does this relate to?

Router

Describe the bug

When a virtual route config mounts two physical() directories under different paths, route files with the same path relative to their mounted directory get the same generated variable name. The generated routeTree.gen.ts then declares the same import binding and the same const twice, so the Vite build fails with "Identifier IndexRouteImport has already been declared".

Route ids and paths are generated correctly (/accounts/, /billing/); only the variable names collide.

Complete minimal reproducer

https://stackblitz.com/edit/github-eufsm66w?file=vite.config.js

Steps to Reproduce the Bug
  1. npm install
  2. npm build or npm run dev
[PARSE_ERROR] Identifier `IndexRouteImport` has already been declared
    ╭─[ src/routeTree.gen.ts:12:19 ]
    │
 12 │ import { Route as IndexRouteImport } from './features/accounts/routes/index'
    │                   ────────┬───────  
    │                           ╰───────── `IndexRouteImport` has already been declared here
 13 │ import { Route as IndexRouteImport } from './features/billing/routes/index'
    │                   ────────┬───────  
    │                           ╰───────── It can not be redeclared here
────╯

Generated src/routeTree.gen.ts:

import { Route as rootRouteImport } from './routes/__root'
import { Route as IndexRouteImport } from './features/accounts/routes/index'
import { Route as IndexRouteImport } from './features/billing/routes/index'

const IndexRoute = IndexRouteImport.update({
  id: '/accounts/',
  path: '/accounts/',
  getParentRoute: () => rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({
  id: '/billing/',
  path: '/billing/',
  getParentRoute: () => rootRouteImport,
} as any)
Expected behavior

Distinct names derived from the route path, as file-based routing produces for routes/accounts/index.tsx and routes/billing/index.tsx: AccountsIndexRouteImport / BillingIndexRouteImport.

Screenshots or Videos

No response

Platform
  • OS: macOS
  • Node: v24.20.0
  • @tanstack/router-plugin: 1.168.48
  • @tanstack/router-generator: 1.167.46 (same code on main)
  • @tanstack/virtual-file-routes: 1.162.0
  • @tanstack/react-router: 1.170.46
  • vite: 8.3.5
Additional context

Cause

packages/router-generator/src/filesystem/virtual/getRouteNodes.ts, physical branch of getRouteNodesRecursive. For each file in the mounted directory:


const pathPrefix = cleanPath(`${parent?.routePath ?? ''}${routePathPrefix}`) 
// '/accounts' + '' = '/accounts'

const routePath = cleanPath(`${pathPrefix}${subtreeNode.routePath}`)
// '/accounts' + '/' = '/accounts/' (correct)

subtreeNode.variableName = routePathToVariable(
  `${routePathPrefix}/${removeExt(subtreeNode.filePath)}`,
)
// '' + '/index' = 'Index' (collides)

The route id is built from pathPrefix, which includes the parent route's path. The variable name is built from routePathPrefix, the prefix given to physical(), which does not. Both mounts use '', so both index files are named Index.

Fix: build the name from pathPrefix as well.

subtreeNode.variableName = routePathToVariable(
  `${pathPrefix}/${removeExt(subtreeNode.filePath)}`,
)

With that change the repro builds and generates AccountsIndexRouteImport and BillingIndexRouteImport.

主要语言
TypeScript
星标
15.3k
派生
1.9k
平均合并
1 天 8 小时
30 天内合并 PR
57

环境准备

在 Codespaces 中打开

在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

TanStack/router 的其他 Issue

查看 TanStack/router 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。