Conversation
|
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 |
|
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 |
Tests Passed |
13b09b2 to
8cfac4c
Compare
There was a problem hiding this comment.
Additional Suggestion:
Telemetry object must be initialized before installBindings is called so that SWC load failure events can be recorded
View Details
📝 Patch Details
diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts
index 49051f0710..2f70e45b9a 100644
--- a/packages/next/src/build/index.ts
+++ b/packages/next/src/build/index.ts
@@ -950,8 +950,6 @@ export default async function build(
// Reading the config can modify environment variables that influence the bundler selection.
bundler = finalizeBundlerFromConfig(bundler)
nextBuildSpan.setAttribute('bundler', getBundlerForTelemetry(bundler))
- // Install the native bindings early so we can have synchronous access later.
- await installBindings(config.experimental?.useWasmBinary)
process.env.NEXT_DEPLOYMENT_ID = config.deploymentId || ''
NextBuildContext.config = config
@@ -962,6 +960,14 @@ export default async function build(
config.distDir = '.next'
}
const distDir = path.join(dir, config.distDir)
+
+ // Initialize telemetry early so it's available if installBindings fails
+ const telemetry = new Telemetry({ distDir })
+ setGlobal('telemetry', telemetry)
+
+ // Install the native bindings early so we can have synchronous access later.
+ await installBindings(config.experimental?.useWasmBinary)
+
NextBuildContext.distDir = distDir
setGlobal('phase', PHASE_PRODUCTION_BUILD)
setGlobal('distDir', distDir)
@@ -1055,10 +1061,6 @@ export default async function build(
const cacheDir = getCacheDir(distDir)
- const telemetry = new Telemetry({ distDir })
-
- setGlobal('telemetry', telemetry)
-
const publicDir = path.join(dir, 'public')
const { pagesDir, appDir } = findPagesDir(dir)
Analysis
Problem
The test "Telemetry CLI > production mode > emits event when swc fails to load" was failing because the NEXT_SWC_LOAD_FAILURE telemetry event was not being emitted when SWC failed to load.
Root Cause
In packages/next/src/build/index.ts, the telemetry object was being initialized AFTER installBindings() was called:
- Line ~952:
await installBindings(config.experimental?.useWasmBinary)was called - Line ~1058: Telemetry was initialized with
const telemetry = new Telemetry({ distDir })
When installBindings() failed and called logLoadFailure() → eventSwcLoadFailure(), the telemetry object retrieved from traceGlobals.get('telemetry') was undefined. The eventSwcLoadFailure() function contains an early return check: if (!telemetry) return, so no event was recorded.
Solution Implemented
Moved the telemetry initialization to occur BEFORE installBindings() is called:
- Moved the
distDircalculation forward (it was needed as a parameter for Telemetry initialization) - Added telemetry initialization immediately after distDir calculation
- Moved
installBindings()call to after telemetry is initialized - Removed the duplicate telemetry initialization that was at the original location
Code Changes
In packages/next/src/build/index.ts:
- Line 961:
const distDir = path.join(dir, config.distDir)(existing, just positioned earlier) - Line 964-966: Added telemetry initialization:
const telemetry = new Telemetry({ distDir }) setGlobal('telemetry', telemetry)
- Line 968:
await installBindings(config.experimental?.useWasmBinary)(moved after telemetry init) - Removed duplicate telemetry initialization that was previously at line ~1058
Why This Works
Now when SWC fails to load with NODE_OPTIONS='--no-addons':
installBindings()callsloadBindings()which failsloadFailure()is called which callsawait eventSwcLoadFailure()eventSwcLoadFailure()now finds the telemetry object in traceGlobals- The event is recorded and flushed with
await telemetry.flush() - With NEXT_TELEMETRY_DEBUG=1, the event is printed to stderr
- The test can successfully find "NEXT_SWC_LOAD_FAILURE" in stderr
Testing
The fix was verified by:
- Confirming telemetry is initialized before installBindings
- Confirming there are no duplicate telemetry initializations
- Confirming setGlobal('telemetry', telemetry) is called
- Tracing through the execution flow to confirm the event will be recorded
Stats from current PR✅ No significant changes detected📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles: **430 kB** → **430 kB** ✅ -3 B82 files with content-based hashes (individual files not comparable between builds) Server Middleware
Build DetailsBuild Manifests
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
|
8cfac4c to
8e6eb98
Compare
There was a problem hiding this comment.
Additional Suggestion:
Telemetry object must be initialized before installBindings is called so that SWC load failure events can be recorded
View Details
📝 Patch Details
diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts
index 49051f0710..2f70e45b9a 100644
--- a/packages/next/src/build/index.ts
+++ b/packages/next/src/build/index.ts
@@ -950,8 +950,6 @@ export default async function build(
// Reading the config can modify environment variables that influence the bundler selection.
bundler = finalizeBundlerFromConfig(bundler)
nextBuildSpan.setAttribute('bundler', getBundlerForTelemetry(bundler))
- // Install the native bindings early so we can have synchronous access later.
- await installBindings(config.experimental?.useWasmBinary)
process.env.NEXT_DEPLOYMENT_ID = config.deploymentId || ''
NextBuildContext.config = config
@@ -962,6 +960,14 @@ export default async function build(
config.distDir = '.next'
}
const distDir = path.join(dir, config.distDir)
+
+ // Initialize telemetry early so it's available if installBindings fails
+ const telemetry = new Telemetry({ distDir })
+ setGlobal('telemetry', telemetry)
+
+ // Install the native bindings early so we can have synchronous access later.
+ await installBindings(config.experimental?.useWasmBinary)
+
NextBuildContext.distDir = distDir
setGlobal('phase', PHASE_PRODUCTION_BUILD)
setGlobal('distDir', distDir)
@@ -1055,10 +1061,6 @@ export default async function build(
const cacheDir = getCacheDir(distDir)
- const telemetry = new Telemetry({ distDir })
-
- setGlobal('telemetry', telemetry)
-
const publicDir = path.join(dir, 'public')
const { pagesDir, appDir } = findPagesDir(dir)
Analysis
Problem
The test "Telemetry CLI > production mode > emits event when swc fails to load" was failing because the NEXT_SWC_LOAD_FAILURE telemetry event was not being emitted when SWC failed to load.
Root Cause
In packages/next/src/build/index.ts, the telemetry object was being initialized AFTER installBindings() was called:
- Line ~952:
await installBindings(config.experimental?.useWasmBinary)was called - Line ~1058: Telemetry was initialized with
const telemetry = new Telemetry({ distDir })
When installBindings() failed and called logLoadFailure() → eventSwcLoadFailure(), the telemetry object retrieved from traceGlobals.get('telemetry') was undefined. The eventSwcLoadFailure() function contains an early return check: if (!telemetry) return, so no event was recorded.
Solution Implemented
Moved the telemetry initialization to occur BEFORE installBindings() is called:
- Moved the
distDircalculation forward (it was needed as a parameter for Telemetry initialization) - Added telemetry initialization immediately after distDir calculation
- Moved
installBindings()call to after telemetry is initialized - Removed the duplicate telemetry initialization that was at the original location
Code Changes
In packages/next/src/build/index.ts:
- Line 961:
const distDir = path.join(dir, config.distDir)(existing, just positioned earlier) - Line 964-966: Added telemetry initialization:
const telemetry = new Telemetry({ distDir }) setGlobal('telemetry', telemetry)
- Line 968:
await installBindings(config.experimental?.useWasmBinary)(moved after telemetry init) - Removed duplicate telemetry initialization that was previously at line ~1058
Why This Works
Now when SWC fails to load with NODE_OPTIONS='--no-addons':
installBindings()callsloadBindings()which failsloadFailure()is called which callsawait eventSwcLoadFailure()eventSwcLoadFailure()now finds the telemetry object in traceGlobals- The event is recorded and flushed with
await telemetry.flush() - With NEXT_TELEMETRY_DEBUG=1, the event is printed to stderr
- The test can successfully find "NEXT_SWC_LOAD_FAILURE" in stderr
Testing
The fix was verified by:
- Confirming telemetry is initialized before installBindings
- Confirming there are no duplicate telemetry initializations
- Confirming setGlobal('telemetry', telemetry) is called
- Tracing through the execution flow to confirm the event will be recorded
Merging this PR will not alter performanceSummary
Comparing Footnotes
|

Somewhat surprisingly, no breaking API changes
swc-project/swc@v1.15.5...v1.15.8 tracks the changes