diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts index 016a9288891a6..6b9a25cc94579 100644 --- a/packages/next/src/build/webpack-config.ts +++ b/packages/next/src/build/webpack-config.ts @@ -882,6 +882,9 @@ export default async function getBaseWebpackConfig( extensions: isNodeServer ? ['.js', '.mjs', '.tsx', '.ts', '.jsx', '.json', '.wasm'] : ['.mjs', '.js', '.tsx', '.ts', '.jsx', '.json', '.wasm'], + extensionAlias: { + '.js': ['.ts', '.tsx', '.js', '.jsx'], + }, modules: [ 'node_modules', ...nodePathList, // Support for NODE_PATH environment variable diff --git a/packages/next/src/lib/typescript/writeConfigurationDefaults.ts b/packages/next/src/lib/typescript/writeConfigurationDefaults.ts index f8f4ce8ec4736..1258396e19db5 100644 --- a/packages/next/src/lib/typescript/writeConfigurationDefaults.ts +++ b/packages/next/src/lib/typescript/writeConfigurationDefaults.ts @@ -48,6 +48,8 @@ function getDesiredCompilerOptions( ts.ModuleKind.ESNext, ts.ModuleKind.CommonJS, ts.ModuleKind.AMD, + ts.ModuleKind.NodeNext, + ts.ModuleKind.Node16, ], value: 'esnext', reason: 'for dynamic import() support', diff --git a/test/integration/tsconfig-verifier/test/index.test.js b/test/integration/tsconfig-verifier/test/index.test.js index 48e9a2cafde16..18bccf6797341 100644 --- a/test/integration/tsconfig-verifier/test/index.test.js +++ b/test/integration/tsconfig-verifier/test/index.test.js @@ -359,6 +359,55 @@ describe('tsconfig.json verifier', () => { `) }) + it('allows you to set node16 module mode', async () => { + expect(await exists(tsConfig)).toBe(false) + + await writeFile( + tsConfig, + `{ "compilerOptions": { "esModuleInterop": false, "module": "node16", "moduleResolution": "node16" } }` + ) + await new Promise((resolve) => setTimeout(resolve, 500)) + const { code, stderr, stdout } = await nextBuild(appDir, undefined, { + stderr: true, + stdout: true, + }) + expect(stderr + stdout).not.toContain('moduleResolution') + expect(code).toBe(0) + + expect(await readFile(tsConfig, 'utf8')).toMatchInlineSnapshot(` + "{ + \\"compilerOptions\\": { + \\"esModuleInterop\\": true, + \\"module\\": \\"node16\\", + \\"moduleResolution\\": \\"node16\\", + \\"lib\\": [ + \\"dom\\", + \\"dom.iterable\\", + \\"esnext\\" + ], + \\"allowJs\\": true, + \\"skipLibCheck\\": true, + \\"strict\\": false, + \\"forceConsistentCasingInFileNames\\": true, + \\"noEmit\\": true, + \\"incremental\\": true, + \\"resolveJsonModule\\": true, + \\"isolatedModules\\": true, + \\"jsx\\": \\"preserve\\" + }, + \\"include\\": [ + \\"next-env.d.ts\\", + \\"**/*.ts\\", + \\"**/*.tsx\\" + ], + \\"exclude\\": [ + \\"node_modules\\" + ] + } + " + `) + }) + it('allows you to extend another configuration file', async () => { expect(await exists(tsConfig)).toBe(false) expect(await exists(tsConfigBase)).toBe(false) diff --git a/test/integration/webpack-config-extensionalias/components/TsxComponent.tsx b/test/integration/webpack-config-extensionalias/components/TsxComponent.tsx new file mode 100644 index 0000000000000..076b2f492eb0e --- /dev/null +++ b/test/integration/webpack-config-extensionalias/components/TsxComponent.tsx @@ -0,0 +1,5 @@ +import React from 'react' + +export function TsxComponent() { + return <>import me +} diff --git a/test/integration/webpack-config-extensionalias/next.config.js b/test/integration/webpack-config-extensionalias/next.config.js new file mode 100644 index 0000000000000..32facfdb9d19b --- /dev/null +++ b/test/integration/webpack-config-extensionalias/next.config.js @@ -0,0 +1,5 @@ +module.exports = { + webpack(config) { + return config + }, +} diff --git a/test/integration/webpack-config-extensionalias/pages/pagewithimport.js b/test/integration/webpack-config-extensionalias/pages/pagewithimport.js new file mode 100644 index 0000000000000..3588de494493d --- /dev/null +++ b/test/integration/webpack-config-extensionalias/pages/pagewithimport.js @@ -0,0 +1,9 @@ +// import tsx file with .js extension alias, this leads to a build fail if extensionAlias is not configured +import { TsxComponent } from '../components/TsxComponent.js' +export default function PageWithImport() { + return ( + <> + See import here: + + ) +} diff --git a/test/integration/webpack-config-extensionalias/test/index.test.js b/test/integration/webpack-config-extensionalias/test/index.test.js new file mode 100644 index 0000000000000..c6eada16f8576 --- /dev/null +++ b/test/integration/webpack-config-extensionalias/test/index.test.js @@ -0,0 +1,12 @@ +import { join } from 'path' +import { nextBuild } from 'next-test-utils' + +const appDir = join(__dirname, '../') + +describe('webpack config with extensionAlias setting', () => { + it('should run correctly with an tsx file import with .js extension', async () => { + const { code } = await nextBuild(appDir, [], {}) + + expect(code).toBe(0) + }) +})