Fails to build in bun-only environment when using `virtualRouteConfig`
Which project does this relate to?
Router
Describe the bug
// vite.config.ts
tanstackStart({
router: {
virtualRouteConfig: 'src/routes.ts',
},
}),
When using virtualRouteConfig with tanstack/start, loadConfigFile uses tsx behind the scenes to load the config file. The problem is that tsx is node specific and doesn't work with bun.
The hacky solution is to make sure your environment also has node installed. (So I've updated our Dockerfile to install node before running vite build, but then it continues to use bun to serve the server).
I am unsure what the full solution should be... change how the virtualRouteConfig gets loaded? add a "bun" flag?
Your Example Website or App
I could build a full reproduction but it would take a lot of time when the issue is easy to see in the code (it uses tsx!)
Steps to Reproduce the Bug or Issue
- use
virtualRouteConfigand try to build with only bun.
Expected behavior
I would expect tanstack/start to work with bun when using virtualRouteConfig.
Screenshots or Videos
No response
Platform
- Router / Start Version: 1.134.10 (but the issue is there in latest)
- OS: mac
- Browser: n/a
- Browser Version: n/a
- Bundler: vite
- Bundler Version: 6
Additional context
No response
๐ CodeRabbit Plan Mode
Generate an implementation plan and agent prompts for this issue.
โ Successfully generated implementation plan.
๐ก Use @coderabbitai <feedback> to replan
๐ Similar Issues
Related Issues
๐ Related PRs
TanStack/router#5422 - fix(router-devtools-core): actually bundle solid [merged] TanStack/router#5816 - docs(solid-start): start-bun example [merged] TanStack/router#5847 - docs(solid-start): start-large example [merged] TanStack/router#5849 - docs(solid-start): start-tailwind-v4 [merged]
๐ค Suggested Assignees
- birkskyum
- harrytran998
- akawahuynh
- benmccann
๐งช Issue enrichment is currently in early access.
To disable automatic issue enrichment, add the following to your .coderabbit.yaml:
issue_enrichment:
auto_enrich:
enabled: false
for now you should be able to import the config yourself and pass it in instead of the filename
for now you should be able to import the config yourself and pass it in instead of the filename
oh. that is a much better solution! thank you!
Maybe passing in a file path should be deprecated and the docs should guide towards passing in the route config object itself?
Implementation Plan
Approach
Enable TanStack Start's virtualRouteConfig feature to work in Bun runtime by making the config file loading mechanism runtime-aware, allowing it to use Bun's native TypeScript import instead of the Node-specific tsx loader.
Observations
The router-generator package provides utilities for generating TanStack Router route trees from both physical file system structures and virtual route configurations. The virtual route config loader (loadConfigFile.ts) currently uses tsx's tsImport API to dynamically load TypeScript configuration files at runtime. This function is used by both virtual and physical route node generators when loading external or inline route configuration files. The codebase currently assumes a Node.js runtime and uses Node-specific APIs (node:fs, node:path, node:url) throughout.
Assumptions
Assumption 1: Runtime Detection Method
Options Considered:
- Check
typeof Bun !== "undefined"- requires bun-types to avoid TypeScript errors - Check
process.versions.bun- safer in TypeScript environments and more idiomatic
Chosen Option: Use process.versions.bun for detection
Rationale: This approach is TypeScript-safe, doesn't require additional type definitions, and aligns with standard Node.js version detection patterns. Developers familiar with Node.js will recognize this pattern immediately.
Assumption 2: Scope of Runtime Support
Options Considered:
- Add support for Bun only
- Add abstraction layer for multiple runtimes (Bun, Deno, Node)
Chosen Option: Focus solely on Bun support for now
Rationale: The ticket specifically requests Bun support, and adding a more complex abstraction layer would be over-engineering. If Deno or other runtime support is needed later, the runtime detection pattern can be extended following the same approach established here.
๐ก User Tips
Regenerate the plan with different choices with @coderabbitai <feedback>.
Plan
Add Bun Runtime Support to Config File Loading
This phase modifies the config file loading mechanism to detect and handle both Node.js and Bun runtimes, ensuring the virtualRouteConfig feature works in both environments without requiring Node.js installation in Bun-only environments.
Task 1: Add Runtime Detection Logic
Implement runtime detection to determine whether code is executing in Bun or Node.js environment.
- Add conditional check using
process.versions.bunat the start ofloadConfigFilefunction inpackages/router-generator/src/filesystem/virtual/loadConfigFile.ts - The check should determine which import strategy to use without adding external dependencies
Task 2: Implement Dual Import Strategy
Create separate code paths for Bun's native TypeScript import and Node.js tsx import.
- For Bun runtime: Use native
import()function with the file URL, which Bun handles natively without requiring tsx - For Node.js runtime: Preserve existing tsx
tsImportlogic to maintain backward compatibility - Both paths should convert file paths to URLs using
pathToFileURLfromnode:url - Both paths must return the same module exports object structure to ensure consistent behavior for downstream consumers
Task 3: Ensure Error Handling Consistency
Update error handling to provide clear feedback regardless of runtime.
- Catch and handle import failures from both the native
import()(Bun) andtsImport(Node) paths - Ensure error messages indicate which runtime was detected if import fails
- Maintain the existing error contract expected by
getRouteNodes.tsin both virtual and physical filesystem modules
๐ค Prompt for AI agents
Modify the config file loading mechanism to support both Bun and Node.js
runtimes, enabling virtualRouteConfig to work in Bun environments.
In `packages/router-generator/src/filesystem/virtual/loadConfigFile.ts`:
- Add runtime detection at the start of `loadConfigFile` using
`process.versions.bun` check
- Implement conditional import strategy: use native `import()` with
`pathToFileURL` for Bun runtime, preserve existing tsx `tsImport` for Node.js
- Ensure both paths convert file paths to URLs and return consistent module
exports structure
- Add error handling for both import paths with runtime-specific error messages
- Maintain backward compatibility and existing error contract for downstream
consumers
๐ Next Steps
๐ค All AI agent prompts combined
Modify the config file loading mechanism to support both Bun and Node.js
runtimes, enabling virtualRouteConfig to work in Bun environments.
In `packages/router-generator/src/filesystem/virtual/loadConfigFile.ts`:
- Add runtime detection at the start of `loadConfigFile` using
`process.versions.bun` check
- Implement conditional import strategy: use native `import()` with
`pathToFileURL` for Bun runtime, preserve existing tsx `tsImport` for Node.js
- Ensure both paths convert file paths to URLs and return consistent module
exports structure
- Add error handling for both import paths with runtime-specific error messages
- Maintain backward compatibility and existing error contract for downstream
consumers
๐ก Iterate on the plan with:
@coderabbitai <feedback>
Example Feedback
- @coderabbitai You can skip phase 3. Add a simple unit test case for phase 2.
- @coderabbitai For assumption 1 go ahead with option 3 and replan.