Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ To use breakpoints and explore code execution, you can use the ["Run and Debug"]

Some errors are masked and hidden away because of the layers of abstraction and sandboxed nature added by Vitest, Playwright, and Chromium. In order to see what's actually going wrong and the contents of the devtools console in those instances, follow this setup:

1. Add a `debugger` statement to the `playground/vitestSetup.ts` -> `afterAll` hook. This will pause execution before the tests quit and the Playwright browser instance exits.
1. Add an `afterAll` hook with a `debugger` statement to `playground/vitestSetup.ts`. This will pause execution before the tests quit and the Playwright browser instance exits.

2. Run the tests with the `debug-serve` script command, which will enable remote debugging: `pnpm run debug-serve resolve`.

Expand Down
14 changes: 14 additions & 0 deletions docs/config/shared-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,20 @@ Ensure that `@vitejs/devtools` is installed as a dependency. This feature is cur

See [Vite DevTools](https://github.com/vitejs/devtools) for more details.

## tsconfig

- **Type:** `string`

Path to the TypeScript configuration file used by Vite. Relative paths are resolved from the project [`root`](#root).

When this option is not set, Vite discovers the closest matching `tsconfig.json` for each file. See [TypeScript Compiler Options](/guide/features#typescript-compiler-options) for more details.

::: warning Prefer automatic discovery
Setting this option is discouraged because it overrides Vite's per-file tsconfig discovery which is aligned with TypeScript language server. Prefer placing a `tsconfig.json` near the files it configures and using TypeScript [`references`](https://www.typescriptlang.org/tsconfig/#references) for multi-project setups.

If the goal is to remap imports, prefer [`resolve.alias`](#resolve-alias) or the `imports` and `exports` fields in `package.json` instead of selecting a tsconfig solely for [`compilerOptions.paths`](https://www.typescriptlang.org/tsconfig/#paths). Use this option only when automatic discovery cannot identify the intended configuration.
:::

## future

- **Type:** `Record<string, 'warn' | undefined>`
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export type { T }

### TypeScript Compiler Options

Vite respects some of the options in `tsconfig.json` and sets the corresponding Oxc Transformer options. For each file, Vite uses the closest parent `tsconfig.json` that matches the file, or a config referenced by its [`references`](https://www.typescriptlang.org/tsconfig/#references) field that matches the file. Vite treats a config as matching the file when the file satisfies the config's [`files`](https://www.typescriptlang.org/tsconfig/#files), [`include`](https://www.typescriptlang.org/tsconfig/#include), and [`exclude`](https://www.typescriptlang.org/tsconfig/#exclude) fields.
Vite respects some of the options in `tsconfig.json` and sets the corresponding Oxc Transformer options. By default, Vite uses the closest parent `tsconfig.json` that matches each file. A config referenced by that config's [`references`](https://www.typescriptlang.org/tsconfig/#references) field is used when it matches the file. Vite treats a config as matching the file when the file satisfies the config's [`files`](https://www.typescriptlang.org/tsconfig/#files), [`include`](https://www.typescriptlang.org/tsconfig/#include), and [`exclude`](https://www.typescriptlang.org/tsconfig/#exclude) fields.

When the options are set in both the Vite config and the `tsconfig.json`, the value in the Vite config takes precedence.

Expand Down
24 changes: 23 additions & 1 deletion packages/vite/src/node/__tests__/build.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {
RollupLog,
} from 'rolldown'
import { afterEach, describe, expect, assert, test, vi } from 'vitest'
import { BuildEnvironment, resolveConfig } from '..'
import { BuildEnvironment, normalizePath, resolveConfig } from '..'
import type { LibraryFormats, LibraryOptions } from '../build'
import {
ChunkMetadataMap,
Expand Down Expand Up @@ -488,6 +488,28 @@ describe('resolveBuildOutputs', () => {
expect(options.input).toBe('explicit-entry.js')
})

test('top-level tsconfig applies to Rolldown options', async () => {
const builder = await createBuilder({
root: buildProjectRoot,
logLevel: 'silent',
tsconfig: './custom.tsconfig.json',
build: {
rolldownOptions: {
tsconfig: './other.tsconfig.json',
resolve: { tsconfigFilename: './legacy.tsconfig.json' },
},
},
})
const options = resolveRolldownOptions(
builder.environments.client,
new ChunkMetadataMap(),
)
expect(options.tsconfig).toBe(
normalizePath(resolve(buildProjectRoot, 'custom.tsconfig.json')),
)
expect(options.resolve?.tsconfigFilename).toBeUndefined()
})

test('falls back to index.html when no input is set', async () => {
const builder = await createBuilder({
root: buildProjectRoot,
Expand Down
25 changes: 25 additions & 0 deletions packages/vite/src/node/__tests__/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,31 @@ describe('resolveConfig', () => {
expect(results2.clearScreen).toBe(false)
})

test('resolves the configured tsconfig path', async () => {
const root = path.resolve(import.meta.dirname, 'fixtures')
const resolved = await resolveConfig(
{ root, tsconfig: './custom.tsconfig.json' },
'build',
)
expect(resolved.tsconfig).toBe(
normalizePath(path.resolve(root, 'custom.tsconfig.json')),
)

const absoluteTsconfig = path.resolve(root, 'absolute.tsconfig.json')
expect(
(
await resolveConfig(
{ root, tsconfig: absoluteTsconfig, configFile: false },
'build',
)
).tsconfig,
).toBe(normalizePath(absoluteTsconfig))

expect(
(await resolveConfig({ root, configFile: false }, 'build')).tsconfig,
).toBeUndefined()
})

test('resolveConfig with root path including "#" and "?" and "*" should warn ', async () => {
expect.assertions(1)

Expand Down
34 changes: 34 additions & 0 deletions packages/vite/src/node/__tests__/plugins/oxc.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from 'node:path'
import { describe, expect, test } from 'vitest'
import { resolveConfig } from '../../config'
import { transformWithOxc } from '../../plugins/oxc'

describe('transformWithOxc', () => {
Expand Down Expand Up @@ -153,4 +154,37 @@ describe('transformWithOxc', () => {
)
expect(result?.code).toContain('_decorateMetadata("design:type"')
})

test('uses the configured tsconfig instead of automatic discovery', async () => {
const code = `
class Foo {
bar = 'bar'
}
`
const fixtures = path.resolve(
import.meta.dirname,
'./fixtures/oxc-tsconfigs',
)
const explicitTsconfig = path.resolve(
fixtures,
'use-define-false/tsconfig.json',
)
const config = await resolveConfig(
{ root: fixtures, tsconfig: explicitTsconfig, configFile: false },
'serve',
)
const expected = await transformWithOxc(
code,
path.resolve(fixtures, 'use-define-false/bar.ts'),
{ target: 'esnext' },
)
const actual = await transformWithOxc(
code,
path.resolve(fixtures, 'use-define-true/bar.ts'),
{ target: 'esnext' },
undefined,
config,
)
expect(actual.code).toBe(expected.code)
})
})
7 changes: 7 additions & 0 deletions packages/vite/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,13 @@ export function resolveRolldownOptions(
: false,
// cache: options.watch ? undefined : false,
...options.rolldownOptions,
tsconfig: environment.config.tsconfig ?? options.rolldownOptions.tsconfig,
resolve: environment.config.tsconfig
? {
...options.rolldownOptions.resolve,
tsconfigFilename: undefined,
}
: options.rolldownOptions.resolve,
output: options.rolldownOptions.output,
input,
plugins,
Expand Down
8 changes: 8 additions & 0 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,11 @@ export interface UserConfig extends DefaultEnvironmentOptions {
* @default process.cwd()
*/
root?: string
/**
* Path to the TypeScript configuration file. Relative paths are resolved
* from the project root.
*/
tsconfig?: string
/**
* Base public path when served in development or production.
* @default '/'
Expand Down Expand Up @@ -2032,6 +2037,9 @@ export async function resolveConfig(
),
inlineConfig,
root: resolvedRoot,
tsconfig: config.tsconfig
? normalizePath(path.resolve(resolvedRoot, config.tsconfig))
: undefined,
base,
decodedBase: decodeBase(base),
rawBase: resolvedBase,
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/esbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ export function getTSConfigResolutionCache(
}
let cache = tsconfigResolutionCacheMap.get(config)
if (!cache) {
cache = new TsconfigCache()
cache = new TsconfigCache(config.tsconfig)
tsconfigResolutionCacheMap.set(config, cache)
}
return cache
Expand Down
5 changes: 4 additions & 1 deletion packages/vite/src/node/plugins/oxc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ export async function transformWithOxc(
filename,
code,
resolvedOptions,
getTSConfigResolutionCache(config),
options?.tsconfig === undefined || options.tsconfig === config?.tsconfig
? getTSConfigResolutionCache(config)
: undefined,
)
if (
watcher &&
Expand Down Expand Up @@ -292,6 +294,7 @@ export function oxcPlugin(config: ResolvedConfig): Plugin {

return nativeTransformPlugin({
root: environment.config.root,
tsconfig: environment.config.tsconfig,
include,
exclude,
jsxRefreshInclude,
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/plugins/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ export function oxcResolvePlugin(
: [options.noExternal]

const plugin = viteResolvePlugin({
tsconfig: partialEnv.config.tsconfig,
resolveOptions: {
isBuild: options.isBuild,
isProduction: options.isProduction,
Expand Down
1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ allowBuilds:
unrs-resolver: true
workerd: true

minimumReleaseAgeExcludePrune: true
minimumReleaseAgeExclude:
- rolldown
- '@rolldown/binding-*'
Expand Down
Loading