Skip to content

Commit 67468f9

Browse files
loettzijjk
andauthored
Add support for tsconfig 'nodenext' | 'node16' (#44177)
## ESM: support module option for tsconfig.json - fixes #37525 - fixes #41961 With [TypeScript 4.7 providing ECMAScript Module Support](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/#ecmascript-module-support-in-node-js), we can now set this in our tsconfig.json file for the [module](https://www.typescriptlang.org/tsconfig#module) option. Webpack added "extensionAlias" to solve importing ts files with .js extension -> webpack/enhanced-resolve#351 Co-authored-by: JJ Kasper <[email protected]>
1 parent b4c80c9 commit 67468f9

File tree

7 files changed

+85
-0
lines changed

7 files changed

+85
-0
lines changed

packages/next/src/build/webpack-config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,9 @@ export default async function getBaseWebpackConfig(
882882
extensions: isNodeServer
883883
? ['.js', '.mjs', '.tsx', '.ts', '.jsx', '.json', '.wasm']
884884
: ['.mjs', '.js', '.tsx', '.ts', '.jsx', '.json', '.wasm'],
885+
extensionAlias: {
886+
'.js': ['.ts', '.tsx', '.js', '.jsx'],
887+
},
885888
modules: [
886889
'node_modules',
887890
...nodePathList, // Support for NODE_PATH environment variable

packages/next/src/lib/typescript/writeConfigurationDefaults.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ function getDesiredCompilerOptions(
4848
ts.ModuleKind.ESNext,
4949
ts.ModuleKind.CommonJS,
5050
ts.ModuleKind.AMD,
51+
ts.ModuleKind.NodeNext,
52+
ts.ModuleKind.Node16,
5153
],
5254
value: 'esnext',
5355
reason: 'for dynamic import() support',

test/integration/tsconfig-verifier/test/index.test.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,55 @@ describe('tsconfig.json verifier', () => {
359359
`)
360360
})
361361

362+
it('allows you to set node16 module mode', async () => {
363+
expect(await exists(tsConfig)).toBe(false)
364+
365+
await writeFile(
366+
tsConfig,
367+
`{ "compilerOptions": { "esModuleInterop": false, "module": "node16", "moduleResolution": "node16" } }`
368+
)
369+
await new Promise((resolve) => setTimeout(resolve, 500))
370+
const { code, stderr, stdout } = await nextBuild(appDir, undefined, {
371+
stderr: true,
372+
stdout: true,
373+
})
374+
expect(stderr + stdout).not.toContain('moduleResolution')
375+
expect(code).toBe(0)
376+
377+
expect(await readFile(tsConfig, 'utf8')).toMatchInlineSnapshot(`
378+
"{
379+
\\"compilerOptions\\": {
380+
\\"esModuleInterop\\": true,
381+
\\"module\\": \\"node16\\",
382+
\\"moduleResolution\\": \\"node16\\",
383+
\\"lib\\": [
384+
\\"dom\\",
385+
\\"dom.iterable\\",
386+
\\"esnext\\"
387+
],
388+
\\"allowJs\\": true,
389+
\\"skipLibCheck\\": true,
390+
\\"strict\\": false,
391+
\\"forceConsistentCasingInFileNames\\": true,
392+
\\"noEmit\\": true,
393+
\\"incremental\\": true,
394+
\\"resolveJsonModule\\": true,
395+
\\"isolatedModules\\": true,
396+
\\"jsx\\": \\"preserve\\"
397+
},
398+
\\"include\\": [
399+
\\"next-env.d.ts\\",
400+
\\"**/*.ts\\",
401+
\\"**/*.tsx\\"
402+
],
403+
\\"exclude\\": [
404+
\\"node_modules\\"
405+
]
406+
}
407+
"
408+
`)
409+
})
410+
362411
it('allows you to extend another configuration file', async () => {
363412
expect(await exists(tsConfig)).toBe(false)
364413
expect(await exists(tsConfigBase)).toBe(false)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import React from 'react'
2+
3+
export function TsxComponent() {
4+
return <>import me</>
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
webpack(config) {
3+
return config
4+
},
5+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// import tsx file with .js extension alias, this leads to a build fail if extensionAlias is not configured
2+
import { TsxComponent } from '../components/TsxComponent.js'
3+
export default function PageWithImport() {
4+
return (
5+
<>
6+
See import here: <TsxComponent />
7+
</>
8+
)
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { join } from 'path'
2+
import { nextBuild } from 'next-test-utils'
3+
4+
const appDir = join(__dirname, '../')
5+
6+
describe('webpack config with extensionAlias setting', () => {
7+
it('should run correctly with an tsx file import with .js extension', async () => {
8+
const { code } = await nextBuild(appDir, [], {})
9+
10+
expect(code).toBe(0)
11+
})
12+
})

0 commit comments

Comments
 (0)