Skip to content

Commit e57e275

Browse files
authored
fix(typescript): worker execution failed with custom next.config.js (#37125)
## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [ ] Errors have helpful link attached, see `contributing.md` The PR fixes #37122, an issue introduced by #37105. `next.config.js` might/will include functions (custom `webpack`, `generateBuildId`, `exportPathsMap`, etc.) that are not able to pass from the main thread to a worker. The PR fixes the issue by only passing primitive args to the worker.
1 parent d64512f commit e57e275

File tree

5 files changed

+51
-19
lines changed

5 files changed

+51
-19
lines changed

packages/next/build/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,8 @@ export default async function build(
272272
dir,
273273
[pagesDir, viewsDir].filter(Boolean) as string[],
274274
!ignoreTypeScriptErrors,
275-
config,
275+
config.typescript.tsconfigPath,
276+
config.images.disableStaticImages,
276277
cacheDir,
277278
config.experimental.cpus,
278279
config.experimental.workerThreads
@@ -2353,7 +2354,8 @@ function verifyTypeScriptSetup(
23532354
dir: string,
23542355
intentDirs: string[],
23552356
typeCheckPreflight: boolean,
2356-
config: NextConfigComplete,
2357+
tsconfigPath: string,
2358+
disableStaticImages: boolean,
23572359
cacheDir: string | undefined,
23582360
numWorkers: number | undefined,
23592361
enableWorkerThreads: boolean | undefined
@@ -2376,7 +2378,8 @@ function verifyTypeScriptSetup(
23762378
dir,
23772379
intentDirs,
23782380
typeCheckPreflight,
2379-
config,
2381+
tsconfigPath,
2382+
disableStaticImages,
23802383
cacheDir
23812384
)
23822385
.then((result) => {

packages/next/lib/typescript/getTypeScriptIntent.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { promises as fs } from 'fs'
22
import path from 'path'
3-
import { NextConfigComplete } from '../../server/config-shared'
43
import { fileExists } from '../file-exists'
54
import { recursiveReadDir } from '../recursive-readdir'
65

@@ -9,18 +8,20 @@ export type TypeScriptIntent = { firstTimeSetup: boolean }
98
export async function getTypeScriptIntent(
109
baseDir: string,
1110
intentDirs: string[],
12-
config: NextConfigComplete
11+
tsconfigPath: string
1312
): Promise<TypeScriptIntent | false> {
14-
const tsConfigPath = path.join(baseDir, config.typescript.tsconfigPath)
13+
const resolvedTsConfigPath = path.join(baseDir, tsconfigPath)
1514

1615
// The integration turns on if we find a `tsconfig.json` in the user's
1716
// project.
18-
const hasTypeScriptConfiguration = await fileExists(tsConfigPath)
17+
const hasTypeScriptConfiguration = await fileExists(resolvedTsConfigPath)
1918
if (hasTypeScriptConfiguration) {
20-
const content = await fs.readFile(tsConfigPath, { encoding: 'utf8' }).then(
21-
(txt) => txt.trim(),
22-
() => null
23-
)
19+
const content = await fs
20+
.readFile(resolvedTsConfigPath, { encoding: 'utf8' })
21+
.then(
22+
(txt) => txt.trim(),
23+
() => null
24+
)
2425
return { firstTimeSetup: content === '' || content === '{}' }
2526
}
2627

packages/next/lib/verifyTypeScriptSetup.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { TypeCheckResult } from './typescript/runTypeCheck'
1414
import { writeAppTypeDeclarations } from './typescript/writeAppTypeDeclarations'
1515
import { writeConfigurationDefaults } from './typescript/writeConfigurationDefaults'
1616
import { missingDepsError } from './typescript/missingDependencyError'
17-
import { NextConfigComplete } from '../server/config-shared'
1817

1918
const requiredPackages = [
2019
{ file: 'typescript', pkg: 'typescript', exportsRestrict: false },
@@ -34,14 +33,15 @@ export async function verifyTypeScriptSetup(
3433
dir: string,
3534
intentDirs: string[],
3635
typeCheckPreflight: boolean,
37-
config: NextConfigComplete,
36+
tsconfigPath: string,
37+
disableStaticImages: boolean,
3838
cacheDir?: string
3939
): Promise<{ result?: TypeCheckResult; version: string | null }> {
40-
const tsConfigPath = path.join(dir, config.typescript.tsconfigPath)
40+
const resolvedTsConfigPath = path.join(dir, tsconfigPath)
4141

4242
try {
4343
// Check if the project uses TypeScript:
44-
const intent = await getTypeScriptIntent(dir, intentDirs, config)
44+
const intent = await getTypeScriptIntent(dir, intentDirs, tsconfigPath)
4545
if (!intent) {
4646
return { version: null }
4747
}
@@ -68,17 +68,21 @@ export async function verifyTypeScriptSetup(
6868
}
6969

7070
// Reconfigure (or create) the user's `tsconfig.json` for them:
71-
await writeConfigurationDefaults(ts, tsConfigPath, intent.firstTimeSetup)
71+
await writeConfigurationDefaults(
72+
ts,
73+
resolvedTsConfigPath,
74+
intent.firstTimeSetup
75+
)
7276
// Write out the necessary `next-env.d.ts` file to correctly register
7377
// Next.js' types:
74-
await writeAppTypeDeclarations(dir, !config.images.disableStaticImages)
78+
await writeAppTypeDeclarations(dir, !disableStaticImages)
7579

7680
let result
7781
if (typeCheckPreflight) {
7882
const { runTypeCheck } = require('./typescript/runTypeCheck')
7983

8084
// Verify the project passes type-checking before we go to webpack phase:
81-
result = await runTypeCheck(ts, dir, tsConfigPath, cacheDir)
85+
result = await runTypeCheck(ts, dir, resolvedTsConfigPath, cacheDir)
8286
}
8387
return { result, version: ts.version }
8488
} catch (err) {

packages/next/server/dev/next-dev-server.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,8 @@ export default class DevServer extends Server {
424424
this.dir,
425425
[this.pagesDir!, this.viewsDir].filter(Boolean) as string[],
426426
false,
427-
this.nextConfig
427+
this.nextConfig.typescript.tsconfigPath,
428+
this.nextConfig.images.disableStaticImages
428429
)
429430

430431
this.customRoutes = await loadCustomRoutes(this.nextConfig)

test/integration/typescript/test/index.test.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,29 @@ export default function EvilPage(): JSX.Element {
108108
expect(output.code).toBe(0)
109109
})
110110

111+
it('should build the app with functions in next.config.js', async () => {
112+
const nextConfig = new File(join(appDir, 'next.config.js'))
113+
114+
nextConfig.write(`
115+
module.exports = {
116+
webpack(config) { return config },
117+
onDemandEntries: {
118+
// Make sure entries are not getting disposed.
119+
maxInactiveAge: 1000 * 60 * 60,
120+
},
121+
}
122+
`)
123+
124+
try {
125+
const output = await nextBuild(appDir, [], { stdout: true })
126+
127+
expect(output.stdout).toMatch(/Compiled successfully/)
128+
expect(output.code).toBe(0)
129+
} finally {
130+
nextConfig.restore()
131+
}
132+
})
133+
111134
it('should not inform when using default tsconfig path', async () => {
112135
const output = await nextBuild(appDir, [], { stdout: true })
113136
expect(output.stdout).not.toMatch(/Using tsconfig file:/)

0 commit comments

Comments
 (0)