Skip to content

Commit 8fd06f9

Browse files
authored
Turbopack build: Implement error when using next start without --turbopack (#77678)
### What? This PR adds validation to ensure that the build tool used during `next build` matches the one used during `next start`. It prevents mismatches between Turbopack and Webpack builds. ### Why? When a project is built with Turbopack but started without the `--turbopack` flag (or vice versa), it can lead to unexpected behavior and errors. This change ensures consistency between build and runtime environments. ### How? - Added a constant `IS_TURBOPACK_BUILD_FILE` to track which build tool was used - Added validation in the server startup to check if the `--turbopack` flag matches the build tool that was used - Added appropriate error messages (669 and 670) to provide clear guidance when mismatches occur
1 parent 02287c4 commit 8fd06f9

File tree

4 files changed

+29
-3
lines changed

4 files changed

+29
-3
lines changed

packages/next/errors.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -666,5 +666,7 @@
666666
"665": "Failed to find Server Action \"%s\". This request might be from an older or newer deployment.\\nRead more: https://nextjs.org/docs/messages/failed-to-find-server-action",
667667
"666": "Turbopack builds are only available in canary builds of Next.js.",
668668
"667": "receiveExpiredTags is deprecated, and not expected to be called.",
669-
"668": "Internal Next.js error: Router action dispatched before initialization."
669+
"668": "Internal Next.js error: Router action dispatched before initialization.",
670+
"669": "Invariant: --turbopack is set but the build used Webpack",
671+
"670": "Invariant: --turbopack is not set but the build used Turbopack. Add --turbopack to \"next start\"."
670672
}

packages/next/src/build/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ import {
8181
UNDERSCORE_NOT_FOUND_ROUTE,
8282
DYNAMIC_CSS_MANIFEST,
8383
TURBOPACK_CLIENT_MIDDLEWARE_MANIFEST,
84+
IS_TURBOPACK_BUILD_FILE,
8485
} from '../shared/lib/constants'
8586
import {
8687
getSortedRoutes,
@@ -1452,7 +1453,7 @@ export default async function build(
14521453
let shutdownPromise = Promise.resolve()
14531454
if (!isGenerateMode) {
14541455
if (turboNextBuild) {
1455-
await writeFileUtf8(path.join(distDir, 'IS_TURBOPACK_BUILD'), '')
1456+
await writeFileUtf8(path.join(distDir, IS_TURBOPACK_BUILD_FILE), '')
14561457
const {
14571458
duration: compilerDuration,
14581459
shutdownPromise: p,
@@ -2333,6 +2334,7 @@ export default async function build(
23332334
]
23342335
: []),
23352336
BUILD_ID_FILE,
2337+
turboNextBuild ? IS_TURBOPACK_BUILD_FILE : null,
23362338
path.join(SERVER_DIRECTORY, NEXT_FONT_MANIFEST + '.js'),
23372339
path.join(SERVER_DIRECTORY, NEXT_FONT_MANIFEST + '.json'),
23382340
...instrumentationHookEntryFiles,

packages/next/src/server/next-server.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
PHASE_PRODUCTION_BUILD,
4343
UNDERSCORE_NOT_FOUND_ROUTE_ENTRY,
4444
FUNCTIONS_CONFIG_MANIFEST,
45+
IS_TURBOPACK_BUILD_FILE,
4546
} from '../shared/lib/constants'
4647
import { findDir } from '../lib/find-pages-dir'
4748
import { NodeNextRequest, NodeNextResponse } from './base-http/node'
@@ -188,9 +189,24 @@ export default class NextNodeServer extends BaseServer<
188189
// Initialize super class
189190
super(options)
190191

191-
this.isDev = options.dev ?? false
192+
const isDev = options.dev ?? false
193+
this.isDev = isDev
192194
this.sriEnabled = Boolean(options.conf.experimental?.sri?.algorithm)
193195

196+
const isTurbopackBuild = this.isTurbopackBuild()
197+
198+
if (!isDev) {
199+
if (process.env.TURBOPACK && !isTurbopackBuild) {
200+
throw new Error(
201+
`Invariant: --turbopack is set but the build used Webpack`
202+
)
203+
} else if (!process.env.TURBOPACK && isTurbopackBuild) {
204+
throw new Error(
205+
`Invariant: --turbopack is not set but the build used Turbopack. Add --turbopack to "next start".`
206+
)
207+
}
208+
}
209+
194210
/**
195211
* This sets environment variable to be used at the time of SSR by head.tsx.
196212
* Using this from process.env allows targeting SSR by calling
@@ -510,6 +526,11 @@ export default class NextNodeServer extends BaseServer<
510526
}
511527
}
512528

529+
private isTurbopackBuild(): boolean {
530+
const isTurbopackBuildFile = join(this.distDir, IS_TURBOPACK_BUILD_FILE)
531+
return fs.existsSync(isTurbopackBuildFile)
532+
}
533+
513534
protected getEnabledDirectories(dev: boolean): NextEnabledDirectories {
514535
const dir = dev ? this.dir : this.serverDistDir
515536

packages/next/src/shared/lib/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export const CONFIG_FILES = [
5656
'next.config.ts',
5757
]
5858
export const BUILD_ID_FILE = 'BUILD_ID'
59+
export const IS_TURBOPACK_BUILD_FILE = 'IS_TURBOPACK_BUILD'
5960
export const BLOCKED_PAGES = ['/_document', '/_app', '/_error']
6061
export const CLIENT_PUBLIC_FILES_PATH = 'public'
6162
export const CLIENT_STATIC_FILES_PATH = 'static'

0 commit comments

Comments
 (0)