diff --git a/packages/nuxi/src/utils/prepare.ts b/packages/nuxi/src/utils/prepare.ts index 636930e110..5d9de151ce 100644 --- a/packages/nuxi/src/utils/prepare.ts +++ b/packages/nuxi/src/utils/prepare.ts @@ -14,9 +14,9 @@ export const writeTypes = async (nuxt: Nuxt) => { jsx: 'preserve', target: 'ESNext', module: 'ESNext', - moduleResolution: 'Node', + moduleResolution: nuxt.options.experimental.typescriptBundlerResolution ? 'Bundler' : 'Node', skipLibCheck: true, - strict: nuxt.options.typescript?.strict ?? false, + strict: nuxt.options.typescript?.strict ?? true, allowJs: true, // TODO: remove by default in 3.7 baseUrl: nuxt.options.srcDir, diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index d5ba2f2c4c..70ca6a0547 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -37,6 +37,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { console.warn(`[nuxt] Could not load custom \`spaLoadingTemplate\` path as it does not exist: \`${spaLoadingTemplate}\`.`) } + // @ts-expect-error `typescriptBundlerResolution` coming in next nitro version const nitroConfig: NitroConfig = defu(_nitroConfig, { debug: nuxt.options.debug, rootDir: nuxt.options.rootDir, @@ -44,6 +45,10 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { srcDir: nuxt.options.serverDir, dev: nuxt.options.dev, buildDir: nuxt.options.buildDir, + experimental: { + // @ts-expect-error `typescriptBundlerResolution` coming in next nitro version + typescriptBundlerResolution: nuxt.options.experimental.typescriptBundlerResolution || nuxt.options.typescript?.tsConfig?.compilerOptions?.moduleResolution?.toLowercase() === 'bundler' || _nitroConfig.typescript?.tsConfig?.compilerOptions?.moduleResolution?.toLowercase() === 'bundler' + }, imports: { autoImport: nuxt.options.imports.autoImport as boolean, imports: [ diff --git a/packages/schema/src/config/experimental.ts b/packages/schema/src/config/experimental.ts index 786547e3d4..17507c8f4e 100644 --- a/packages/schema/src/config/experimental.ts +++ b/packages/schema/src/config/experimental.ts @@ -12,8 +12,8 @@ export default defineUntypedSchema({ /** * Enable Vue's reactivity transform * @see https://vuejs.org/guide/extras/reactivity-transform.html - * - * Warning: Reactivity transform feature has been marked as deprecated in Vue 3.3 and is planned to be + * + * Warning: Reactivity transform feature has been marked as deprecated in Vue 3.3 and is planned to be * removed from core in Vue 3.4. * @see https://github.com/vuejs/rfcs/discussions/369#discussioncomment-5059028 */ @@ -107,7 +107,7 @@ export default defineUntypedSchema({ /** * When this option is enabled (by default) payload of pages generated with `nuxt generate` are extracted - * + * * @type {boolean | undefined} */ payloadExtraction: undefined, @@ -147,6 +147,27 @@ export default defineUntypedSchema({ */ configSchema: true, + /** + * This enables 'Bundler' module resolution mode for TypeScript, which is the recommended setting + * for frameworks like Nuxt and Vite. + * + * It improves type support when using modern libraries with `exports`. + * + * This is only not enabled by default because it could be a breaking change for some projects. + * + * See https://github.com/microsoft/TypeScript/pull/51669 + */ + typescriptBundlerResolution: { + async $resolve (val, get) { + if (typeof val === 'boolean') { return val } + const setting = await get('typescript.tsConfig.compilerOptions.moduleResolution') + if (setting) { + return setting.toLowerCase() === 'bundler' + } + return false + } + }, + /** * Whether or not to add a compatibility layer for modules, plugins or user code relying on the old * `@vueuse/head` API. diff --git a/packages/schema/src/config/typescript.ts b/packages/schema/src/config/typescript.ts index 0edfc7ce40..5bf18adc5e 100644 --- a/packages/schema/src/config/typescript.ts +++ b/packages/schema/src/config/typescript.ts @@ -46,7 +46,7 @@ export default defineUntypedSchema({ /** * You can extend generated `.nuxt/tsconfig.json` using this option. - * @type {typeof import('pkg-types')['readPackageJSON']} + * @type {typeof import('pkg-types')['TSConfig']} */ tsConfig: {}, diff --git a/test/fixtures/basic-types/nuxt.config.ts b/test/fixtures/basic-types/nuxt.config.ts index bde94e9aca..f9ec4ab7ec 100644 --- a/test/fixtures/basic-types/nuxt.config.ts +++ b/test/fixtures/basic-types/nuxt.config.ts @@ -2,15 +2,8 @@ import { addTypeTemplate } from 'nuxt/kit' export default defineNuxtConfig({ experimental: { - typedPages: true - }, - typescript: { - strict: true, - tsConfig: { - compilerOptions: { - moduleResolution: process.env.MODULE_RESOLUTION - } - } + typedPages: true, + typescriptBundlerResolution: process.env.MODULE_RESOLUTION === 'bundler' }, buildDir: process.env.NITRO_BUILD_DIR, builder: process.env.TEST_BUILDER as 'webpack' | 'vite' ?? 'vite',