-
Notifications
You must be signed in to change notification settings - Fork 30.2k
perf(dev): print Ready early and defer initialization #87942
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: perf-dev-rust-cli
Are you sure you want to change the base?
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
5aa417d to
991c442
Compare
28a223c to
2b4ccc3
Compare
|
Allow CI Workflow Run
Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer |
991c442 to
ff4ff03
Compare
5b2a7f2 to
e66e783
Compare
5541176 to
e359b2b
Compare
e66e783 to
f3f337e
Compare
e359b2b to
88f6518
Compare
a171bf5 to
619e232
Compare
88f6518 to
ef33eaa
Compare
619e232 to
c62ae55
Compare
ef33eaa to
9bc50a8
Compare
c62ae55 to
d33c633
Compare
9bc50a8 to
b84eb29
Compare
d33c633 to
36fb03c
Compare
b84eb29 to
d3ba612
Compare
46cb939 to
cb347aa
Compare
f952346 to
873efee
Compare
cb347aa to
e695ef9
Compare
873efee to
8336d35
Compare
e695ef9 to
532a088
Compare
8336d35 to
2ef450f
Compare
532a088 to
f573950
Compare
4065f0d to
a7d3863
Compare
3539ff2 to
ef3646c
Compare
a7d3863 to
83c891b
Compare
ef3646c to
a7bd7d3
Compare
83c891b to
3e57cf5
Compare
| // Print "Ready" immediately for fast perceived startup | ||
| // Requests will wait via handlersPromise until init completes | ||
| const startServerProcessDuration = | ||
| performance.mark('next-start-end') && | ||
| performance.measure( | ||
| 'next-start-duration', | ||
| 'next-start', | ||
| 'next-start-end' | ||
| ).duration | ||
| const formatDurationText = | ||
| startServerProcessDuration > 2000 | ||
| ? `${Math.round(startServerProcessDuration / 100) / 10}s` | ||
| : `${Math.round(startServerProcessDuration)}ms` | ||
| Log.event(`Ready in ${formatDurationText}`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "Ready in Xms" message is printed before the heavy initialization completes. If initialization fails (at line 457-469), the misleading "Ready" message has already been logged, but the server exits with an error.
View Details
📝 Patch Details
diff --git a/packages/next/src/server/lib/start-server.ts b/packages/next/src/server/lib/start-server.ts
index ea219758a9..169b46a716 100644
--- a/packages/next/src/server/lib/start-server.ts
+++ b/packages/next/src/server/lib/start-server.ts
@@ -373,21 +373,6 @@ export async function startServer(
logBundler: isDev,
})
- // Print "Ready" immediately for fast perceived startup
- // Requests will wait via handlersPromise until init completes
- const startServerProcessDuration =
- performance.mark('next-start-end') &&
- performance.measure(
- 'next-start-duration',
- 'next-start',
- 'next-start-end'
- ).duration
- const formatDurationText =
- startServerProcessDuration > 2000
- ? `${Math.round(startServerProcessDuration / 100) / 10}s`
- : `${Math.round(startServerProcessDuration)}ms`
- Log.event(`Ready in ${formatDurationText}`)
-
let cleanupStarted = false
let closeUpgraded: (() => void) | null = null
const cleanup = () => {
@@ -474,6 +459,20 @@ export async function startServer(
handlersReady()
+ // Print "Ready" only after successful initialization
+ const startServerProcessDuration =
+ performance.mark('next-start-end') &&
+ performance.measure(
+ 'next-start-duration',
+ 'next-start',
+ 'next-start-end'
+ ).duration
+ const formatDurationText =
+ startServerProcessDuration > 2000
+ ? `${Math.round(startServerProcessDuration / 100) / 10}s`
+ : `${Math.round(startServerProcessDuration)}ms`
+ Log.event(`Ready in ${formatDurationText}`)
+
if (process.env.TURBOPACK && isDev) {
await validateTurboNextConfig({
dir: serverOptions.dir,
Analysis
Misleading "Ready in Xms" message logged before critical initialization completes
What fails: Server prints "Ready in Xms" message at line 389 before calling getRequestHandlers() at line 457. If initialization fails, the "Ready" message has already been logged to the user's console, but then the server exits with an error.
How to reproduce:
- Create a configuration scenario that causes
getRequestHandlers()to throw an error (e.g., corrupted config, missing dependencies during initialization) - Start the Next.js dev server
- Observe that "Ready in Xms" is logged to console
- The server then exits with an error code and prints the error stack trace
Result: Users see misleading output suggesting the server started successfully when it actually failed during initialization.
Expected: The "Ready" message should only be logged after getRequestHandlers() completes successfully. If initialization fails, the "Ready" message should never be printed.
Root cause: Commit 3e57cf5 ("perf(dev): print Ready early and defer initialization") moved the "Ready" log message before the critical getRequestHandlers() initialization call as a performance optimization. While the defensive mechanism via handlersPromise prevents request processing until initialization completes, it does not prevent the misleading log message from being printed on failure.
Fix: Moved the "Ready in Xms" log message to after handlersReady() is called (line 461-475), ensuring it only prints after successful initialization. The log now correctly appears after all critical initialization in getRequestHandlers() completes.
a7bd7d3 to
6d0cb27
Compare
3e57cf5 to
3720986
Compare
6d0cb27 to
b4afc67
Compare
3720986 to
20a8c76
Compare
- Print "Ready in Xms" immediately when HTTP server starts listening - Defer heavy initialization (config, bundler, etc.) to background - First request waits for init via existing handlersPromise mechanism - Fix shell script symlink resolution for pnpm node_modules/.bin - Fix Rust CLI canonicalize for symlink resolution - Extract getSupportedBrowsers to lightweight module This reduces perceived startup time from ~300ms to ~50-100ms. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
❌ 7 failing tests in 3 jobs⏳ CI running (3 jobs reported) · Updated 2026-01-01 20:54:44 UTC · Commit: 79adf32
Details📁
|
b4afc67 to
22b8f36
Compare
20a8c76 to
79adf32
Compare
❌ 121 failing tests in 3 jobs⏳ CI running (3 jobs reported) · Updated 2026-01-01 21:01:15 UTC · Commit: 79adf32
Details📁
|
CodSpeed Performance ReportMerging #87942 will not alter performanceComparing Summary
Footnotes
|

Summary
Benchmark Results (cumulative - final)
Total Improvement (Canary → Final)
Test Plan
🤖 Generated with Claude Code