mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
### What? Two fixes for the Turbopack build tracing introduced in #90397: 1. **Don't block SSG on Turbopack shutdown**: `workerMain()` no longer awaits the shutdown promise before returning. Trace event collection is deferred to `waitForShutdown()`, which the parent process awaits *after* SSG completes. This allows static generation and Turbopack persistence/cache-flush to run in parallel. 2. **Add persistence spans to `trace-build` allowlist**: `turbopack-build-events`, `turbopack-persistence`, and `turbopack-compaction` are now included in the `to-json-build.ts` allowlist so they appear in `.next/trace-build`. ### Why? - The `await shutdownPromise` in `workerMain()` was too eager — it prevented the caller from acknowledging the build as complete and starting SSG until Turbopack persistence finished flushing to disk. - The persistence/compaction spans emitted by Rust (`turbopack-persistence`, `turbopack-compaction`) were not in the `to-json-build.ts` allowlist, so they were silently filtered out of `.next/trace-build`. ### How? **`impl.ts` (worker)**: - Removed `await shutdownPromise` from `workerMain()` — it now returns build results immediately - `waitForShutdown()` now returns `{ debugTraceEvents }` after awaiting shutdown, so trace events are collected only after all compilation events (including persistence spans) have been processed **`index.ts` (parent)**: - Moved `recordTraceEvents(debugTraceEvents)` from the `workerMain` result handler into the `shutdownPromise` `.then()` chain, so events are replayed into the parent reporter after shutdown completes **`to-json-build.ts`**: - Added `turbopack-build-events`, `turbopack-persistence`, `turbopack-compaction` to the allowlist **Test updates**: - Enabled `turbopackFileSystemCacheForBuild: true` in the trace-build test fixture - Updated the Turbopack inline snapshot to include `turbopack-build-events`
47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
import { nextTestSetup } from 'e2e-utils'
|
|
import { join } from 'path'
|
|
import { existsSync } from 'fs'
|
|
import { parseTraceFile } from '../../../lib/parse-trace-file'
|
|
|
|
describe('render-path tracing', () => {
|
|
const { next, isNextDev } = nextTestSetup({
|
|
files: __dirname,
|
|
})
|
|
|
|
if (!isNextDev) {
|
|
it('should be skipped in production', () => {})
|
|
return
|
|
}
|
|
|
|
it('should record render-path events for page requests', async () => {
|
|
const tracePath = join(next.testDir, '.next/dev/trace')
|
|
|
|
// Trigger page request if trace doesn't exist yet
|
|
if (!existsSync(tracePath)) {
|
|
const browser = await next.browser('/')
|
|
expect(await browser.elementByCss('p').text()).toBe('hello world')
|
|
await browser.close()
|
|
await next.stop('SIGTERM')
|
|
await new Promise((resolve) => setTimeout(resolve, 500))
|
|
}
|
|
|
|
const traceStructure = parseTraceFile(tracePath)
|
|
|
|
// Check for render-path events
|
|
const renderPathEvents = traceStructure.eventsByName.get('render-path')
|
|
expect(renderPathEvents).toBeDefined()
|
|
expect(renderPathEvents!.length).toBeGreaterThan(0)
|
|
|
|
// Verify the first render-path event has expected attributes
|
|
const renderEvent = renderPathEvents![0]
|
|
expect(renderEvent.tags).toBeDefined()
|
|
const renderTags = renderEvent.tags as any
|
|
|
|
expect(renderTags.path).toBeDefined()
|
|
expect(typeof renderTags.path).toBe('string')
|
|
|
|
// Verify render event has valid duration
|
|
expect(renderEvent.duration).toBeGreaterThan(0)
|
|
})
|
|
})
|