Skip to content

feat(resolve): allow custom tsconfig file via resolve.tsconfigPaths.configFile#22533

Open
rubnogueira wants to merge 2 commits into
vitejs:mainfrom
rubnogueira:feat/custom-tsconfig
Open

feat(resolve): allow custom tsconfig file via resolve.tsconfigPaths.configFile#22533
rubnogueira wants to merge 2 commits into
vitejs:mainfrom
rubnogueira:feat/custom-tsconfig

Conversation

@rubnogueira
Copy link
Copy Markdown

Summary

Widens resolve.tsconfigPaths from boolean to boolean | TsconfigPathsOptions so consumers can pin a specific tsconfig (e.g. tsconfig.prod.json) instead of relying on rolldown's
auto-discovery.

export default defineConfig(({ mode }) => ({
  resolve: {
    tsconfigPaths: {
      configFile: mode === 'production' ? './tsconfig.prod.json' : './tsconfig.json',
    },
  },
}))

Motivation

resolve.tsconfigPaths: true already works, but only auto-discovers the nearest tsconfig.json. There's no way to point it at a different file. Today users have to either:

  1. Keep the vite-tsconfig-paths plugin (and its projects option), or
  2. Re-read the tsconfig and rebuild resolve.alias by hand in vite.config.ts.

The intended migration story from #22112 was to drop the external plugin once Vite 8 shipped native support, but boolean is too narrow for the cases that motivated
vite-tsconfig-paths.projects in the first place.

Changes

  • packages/vite/src/node/plugins/resolve.ts:
    • New TsconfigPathsOptions { configFile: string } interface.
    • ResolveOptions.tsconfigPaths typed as boolean | TsconfigPathsOptions.
    • Forward the value straight through to rolldown's viteResolvePlugin, resolving a relative configFile against the project root (oxc-resolver requires an absolute path).
  • docs/config/shared-options.md — documents the new shape with the prod/dev switch example.
  • playground/resolve-tsconfig-paths-config-file/ — new e2e playground proving the custom configFile wins over an adjacent (wrong-mapping) tsconfig.json.

Depends on

  • rolldown/rolldown#9571 — widens the napi binding so viteResolvePlugin accepts the object form. Without it, passing { configFile } throws Failed to convert napi value into rust type 'bool' at runtime.

The Rust side already had TsconfigDiscovery::Manual plumbed through oxc_resolver; only the vite-resolve plugin's binding hardcoded bool
(crates/rolldown_plugin_vite_resolve/src/resolver.rs:174 upstream), so the Manual arm was unreachable from JS. The rolldown PR exposes it; this PR forwards it.

Related

Test plan

  • Type-check passes (pnpm typecheck)
  • All packages/vite/src/node/__tests__/resolve.spec.ts cases pass
  • playground/resolve-tsconfig-paths/__tests__/resolve.spec.ts — existing tsconfigPaths: true behavior unchanged
  • playground/resolve-tsconfig-paths-config-file/__tests__/resolve.spec.ts — new playground passes in both dev and build modes
  • tsconfigPaths: false still disables resolution
  • Bumped rolldown to a version that includes the binding widening

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

resolve.tsconfigPaths should accept configuration object

1 participant