diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index eb247a2248955b..8a8346fcbeb1eb 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -681,6 +681,7 @@ export const configDefaults = Object.freeze({ noExternal: [], external: [], preserveSymlinks: false, + tsconfigPaths: false, alias: [], }, @@ -1934,6 +1935,17 @@ assetFileNames isn't equal for every build.rollupOptions.output. A single patter ) } + if ( + resolved.resolve.tsconfigPaths && + resolved.experimental.enableNativePlugin === false + ) { + resolved.logger.warn( + colors.yellow(` +(!) resolve.tsconfigPaths is set to true, but native plugins are disabled. To use resolve.tsconfigPaths, please enable native plugins via experimental.enableNativePlugin. +`), + ) + } + return resolved } @@ -2177,6 +2189,7 @@ async function bundleConfigFile( dedupe: [], extensions: configDefaults.resolve.extensions, preserveSymlinks: false, + tsconfigPaths: false, packageCache, isRequire, builtins: nodeLikeBuiltins, diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 6780894acaa24a..21de6da3556bef 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -114,6 +114,15 @@ export interface ResolveOptions extends EnvironmentResolveOptions { * @default false */ preserveSymlinks?: boolean + /** + * Enable tsconfig paths resolution + * + * This option does not have any effect if `experimental.enableNativePlugin` is set to `false`. + * + * @default false + * @experimental + */ + tsconfigPaths?: boolean } interface ResolvePluginOptions { @@ -266,7 +275,7 @@ export function oxcResolvePlugin( tryIndex: options.tryIndex ?? true, tryPrefix: options.tryPrefix, preserveSymlinks: options.preserveSymlinks, - tsconfigPaths: false, + tsconfigPaths: options.tsconfigPaths, }, environmentConsumer: partialEnv.config.consumer, environmentName: partialEnv.name, diff --git a/packages/vite/src/node/ssr/fetchModule.ts b/packages/vite/src/node/ssr/fetchModule.ts index fabeaaa1e716d8..5c9aac410eddfe 100644 --- a/packages/vite/src/node/ssr/fetchModule.ts +++ b/packages/vite/src/node/ssr/fetchModule.ts @@ -57,6 +57,7 @@ export async function fetchModule( extensions: ['.js', '.cjs', '.json'], dedupe, preserveSymlinks, + tsconfigPaths: false, isBuild: false, isProduction, root, diff --git a/playground/resolve-tsconfig-paths/__tests__/resolve.spec.ts b/playground/resolve-tsconfig-paths/__tests__/resolve.spec.ts new file mode 100644 index 00000000000000..6e4f81d4473d40 --- /dev/null +++ b/playground/resolve-tsconfig-paths/__tests__/resolve.spec.ts @@ -0,0 +1,14 @@ +import { expect, test } from 'vitest' +import { page } from '~utils' + +test('import from .ts', async () => { + await expect.poll(() => page.textContent('.ts')).toMatch('[success]') +}) + +test('import from .js', async () => { + await expect.poll(() => page.textContent('.js')).toMatch('[success]') +}) + +test('fallback works', async () => { + await expect.poll(() => page.textContent('.fallback')).toMatch('[success]') +}) diff --git a/playground/resolve-tsconfig-paths/fallback/fallback.js b/playground/resolve-tsconfig-paths/fallback/fallback.js new file mode 100644 index 00000000000000..3407a59f7c86ac --- /dev/null +++ b/playground/resolve-tsconfig-paths/fallback/fallback.js @@ -0,0 +1 @@ +export default '[success] imported from fallback' diff --git a/playground/resolve-tsconfig-paths/index.html b/playground/resolve-tsconfig-paths/index.html new file mode 100644 index 00000000000000..7dd53fe111dc27 --- /dev/null +++ b/playground/resolve-tsconfig-paths/index.html @@ -0,0 +1,25 @@ +

Resolve: tsconfig paths

+ +

Import from .ts

+

+ +

Import from .js

+

+ +

Fallback works

+

+ + diff --git a/playground/resolve-tsconfig-paths/package.json b/playground/resolve-tsconfig-paths/package.json new file mode 100644 index 00000000000000..e4b0a23a3c65a3 --- /dev/null +++ b/playground/resolve-tsconfig-paths/package.json @@ -0,0 +1,12 @@ +{ + "name": "@vitejs/test-resolve-tsconfig-paths", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "debug": "node --inspect-brk ../../packages/vite/bin/vite", + "preview": "vite preview" + } +} diff --git a/playground/resolve-tsconfig-paths/src/imported.js b/playground/resolve-tsconfig-paths/src/imported.js new file mode 100644 index 00000000000000..49d5a8f82b28e5 --- /dev/null +++ b/playground/resolve-tsconfig-paths/src/imported.js @@ -0,0 +1 @@ +export default '[success] imported' diff --git a/playground/resolve-tsconfig-paths/src/js.js b/playground/resolve-tsconfig-paths/src/js.js new file mode 100644 index 00000000000000..8d1fff745b93ac --- /dev/null +++ b/playground/resolve-tsconfig-paths/src/js.js @@ -0,0 +1 @@ +export { default } from '@/imported' diff --git a/playground/resolve-tsconfig-paths/src/ts.ts b/playground/resolve-tsconfig-paths/src/ts.ts new file mode 100644 index 00000000000000..8d1fff745b93ac --- /dev/null +++ b/playground/resolve-tsconfig-paths/src/ts.ts @@ -0,0 +1 @@ +export { default } from '@/imported' diff --git a/playground/resolve-tsconfig-paths/tsconfig.json b/playground/resolve-tsconfig-paths/tsconfig.json new file mode 100644 index 00000000000000..8d9202c7c1d633 --- /dev/null +++ b/playground/resolve-tsconfig-paths/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "allowJs": true, + "noEmit": true, + "paths": { + "@/*": ["./src/*"], + "@fallback/*": ["./src/*", "./fallback/*"] + } + }, + "exclude": ["./__tests__"] +} diff --git a/playground/resolve-tsconfig-paths/vite.config.js b/playground/resolve-tsconfig-paths/vite.config.js new file mode 100644 index 00000000000000..25158f653fe3fa --- /dev/null +++ b/playground/resolve-tsconfig-paths/vite.config.js @@ -0,0 +1,10 @@ +import { defineConfig } from 'vite' + +export default defineConfig({ + resolve: { + tsconfigPaths: true, + }, + experimental: { + enableNativePlugin: 'resolver', + }, +}) diff --git a/playground/tsconfig.json b/playground/tsconfig.json index cac04a1704fb65..b1517262e11ed4 100644 --- a/playground/tsconfig.json +++ b/playground/tsconfig.json @@ -1,6 +1,6 @@ { "include": ["**/vite*config*", "**/*.ts"], - "exclude": ["**/dist/**", "./legacy/**"], + "exclude": ["**/dist/**", "./legacy/**", "./resolve-tsconfig-paths/**"], "compilerOptions": { "checkJs": true, "target": "ES2023", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ecf885e26473dc..8fc2e4adcb6113 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1313,6 +1313,8 @@ importers: playground/resolve-linked: {} + playground/resolve-tsconfig-paths: {} + playground/resolve/browser-field: dependencies: '@vitejs/test-resolve-browser-field-bare-import-fail':