From ae5fa5d69a1c1472489bb1b90930d0049f023f0f Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Fri, 29 Aug 2025 17:15:17 +0200 Subject: [PATCH 1/7] fix(nextjs): Add edge polyfills for nextjs-13 in dev mode From 330f1729e1f403775bc0e3ee6f9288b7bdec1bab Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Fri, 29 Aug 2025 17:15:24 +0200 Subject: [PATCH 2/7] Add middleware file to nextjs-13 e2e tests to demonstrate failure --- .../e2e-tests/test-applications/nextjs-13/middleware.ts | 6 ++++++ .../nextjs-13/tests/server/cjs-api-endpoints.test.ts | 6 ++++-- .../nextjs-13/tests/server/wrapApiHandlerWithSentry.test.ts | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 dev-packages/e2e-tests/test-applications/nextjs-13/middleware.ts diff --git a/dev-packages/e2e-tests/test-applications/nextjs-13/middleware.ts b/dev-packages/e2e-tests/test-applications/nextjs-13/middleware.ts new file mode 100644 index 000000000000..ad98f4c83cb9 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/nextjs-13/middleware.ts @@ -0,0 +1,6 @@ +import { NextResponse } from 'next/server'; + +export function middleware() { + // Basic middleware to ensure that the build works with edge runtime + return NextResponse.next(); +} diff --git a/dev-packages/e2e-tests/test-applications/nextjs-13/tests/server/cjs-api-endpoints.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-13/tests/server/cjs-api-endpoints.test.ts index 42b2e3727bd6..28cc91e9b879 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-13/tests/server/cjs-api-endpoints.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-13/tests/server/cjs-api-endpoints.test.ts @@ -11,7 +11,8 @@ test('should create a transaction for a CJS pages router API endpoint', async ({ const transactionPromise = waitForTransaction('nextjs-13', async transactionEvent => { return ( transactionEvent.transaction === 'GET /api/cjs-api-endpoint' && - transactionEvent.contexts?.trace?.op === 'http.server' + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction_info?.source === 'route' ); }); @@ -73,7 +74,8 @@ test('should not mess up require statements in CJS API endpoints', async ({ requ const transactionPromise = waitForTransaction('nextjs-13', async transactionEvent => { return ( transactionEvent.transaction === 'GET /api/cjs-api-endpoint-with-require' && - transactionEvent.contexts?.trace?.op === 'http.server' + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction_info?.source === 'route' ); }); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-13/tests/server/wrapApiHandlerWithSentry.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-13/tests/server/wrapApiHandlerWithSentry.test.ts index 3bcc1bbbea92..798ea3409089 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-13/tests/server/wrapApiHandlerWithSentry.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-13/tests/server/wrapApiHandlerWithSentry.test.ts @@ -22,7 +22,11 @@ const cases = [ cases.forEach(({ name, url, transactionName }) => { test(`Should capture transactions for routes with various shapes (${name})`, async ({ request }) => { const transactionEventPromise = waitForTransaction('nextjs-13', transactionEvent => { - return transactionEvent.transaction === transactionName && transactionEvent.contexts?.trace?.op === 'http.server'; + return ( + transactionEvent.transaction === transactionName && + transactionEvent.contexts?.trace?.op === 'http.server' && + transactionEvent.transaction_info?.source === 'route' + ); }); request.get(url).catch(() => { From 46aaac9ea0dfdcfef4d0e97736990e5fb7b6dcf5 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Mon, 8 Sep 2025 16:55:49 +0200 Subject: [PATCH 3/7] Add performance polyfill for webpack dev mode --- packages/nextjs/rollup.npm.config.mjs | 15 +++++++++++ .../nextjs/src/config/polyfills/perf_hooks.js | 25 ++++++++++++++++++ packages/nextjs/src/config/webpack.ts | 26 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 packages/nextjs/src/config/polyfills/perf_hooks.js diff --git a/packages/nextjs/rollup.npm.config.mjs b/packages/nextjs/rollup.npm.config.mjs index 3582cf4574ef..89271a21e9d3 100644 --- a/packages/nextjs/rollup.npm.config.mjs +++ b/packages/nextjs/rollup.npm.config.mjs @@ -88,5 +88,20 @@ export default [ }, }), ), + ...makeNPMConfigVariants( + makeBaseNPMConfig({ + entrypoints: ['src/config/polyfills/perf_hooks.js'], + + packageSpecificConfig: { + output: { + // Preserve the original file structure (i.e., so that everything is still relative to `src`) + entryFileNames: 'config/polyfills/[name].js', + + // make it so Rollup calms down about the fact that we're combining default and named exports + exports: 'named', + }, + }, + }), + ), ...makeOtelLoaders('./build', 'sentry-node'), ]; diff --git a/packages/nextjs/src/config/polyfills/perf_hooks.js b/packages/nextjs/src/config/polyfills/perf_hooks.js new file mode 100644 index 000000000000..fe0c5b84657a --- /dev/null +++ b/packages/nextjs/src/config/polyfills/perf_hooks.js @@ -0,0 +1,25 @@ +// Polyfill for Node.js perf_hooks module in edge runtime +// This mirrors the polyfill from packages/vercel-edge/rollup.npm.config.mjs + +// Ensure performance global is available +if (typeof globalThis !== 'undefined' && globalThis.performance === undefined) { + globalThis.performance = { + timeOrigin: 0, + now: function () { + return Date.now(); + }, + }; +} + +// Export the performance object for perf_hooks compatibility +export const performance = globalThis.performance || { + timeOrigin: 0, + now: function () { + return Date.now(); + }, +}; + +// Default export for CommonJS compatibility +export default { + performance, +}; diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index b336e1e2ee9b..68658de4ada7 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -103,6 +103,11 @@ export function constructWebpackConfigFunction( addOtelWarningIgnoreRule(newConfig); + // Add edge runtime polyfills when building for edge in dev mode + if (runtime === 'edge' && isDev) { + addEdgeRuntimePolyfills(newConfig, buildContext); + } + let pagesDirPath: string | undefined; const maybePagesDirPath = path.join(projectDir, 'pages'); const maybeSrcPagesDirPath = path.join(projectDir, 'src', 'pages'); @@ -865,6 +870,27 @@ function addOtelWarningIgnoreRule(newConfig: WebpackConfigObjectWithModuleRules) } } +function addEdgeRuntimePolyfills(newConfig: WebpackConfigObjectWithModuleRules, buildContext: BuildContext): void { + const { webpack } = buildContext; + + // Use ProvidePlugin to inject performance global only when accessed + newConfig.plugins = newConfig.plugins || []; + newConfig.plugins.push( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + new (webpack as any).ProvidePlugin({ + performance: [path.resolve(__dirname, 'polyfills', 'perf_hooks.js'), 'performance'], + }), + ); + + // Add module resolution aliases for problematic Node.js modules in edge runtime + newConfig.resolve = newConfig.resolve || {}; + newConfig.resolve.alias = { + ...newConfig.resolve.alias, + // Redirect perf_hooks imports to a polyfilled version + perf_hooks: path.resolve(__dirname, 'polyfills', 'perf_hooks.js'), + }; +} + function _getModules(projectDir: string): Record { try { const packageJson = path.join(projectDir, 'package.json'); From 5bb46eab6737185fd367055405649aeb00f0063a Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Mon, 8 Sep 2025 18:26:59 +0200 Subject: [PATCH 4/7] Add performance polyfills for edge runtime on dev mode --- .../test-applications/nextjs-13/middleware.ts | 12 ++--- packages/nextjs/.eslintrc.js | 6 +++ packages/nextjs/src/config/types.ts | 1 + packages/nextjs/src/config/webpack.ts | 5 +- packages/nextjs/test/config/fixtures.ts | 8 ++- .../webpack/constructWebpackConfig.test.ts | 50 +++++++++++++++++++ 6 files changed, 71 insertions(+), 11 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/nextjs-13/middleware.ts b/dev-packages/e2e-tests/test-applications/nextjs-13/middleware.ts index ad98f4c83cb9..b2117419c10f 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-13/middleware.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-13/middleware.ts @@ -1,6 +1,6 @@ -import { NextResponse } from 'next/server'; - -export function middleware() { - // Basic middleware to ensure that the build works with edge runtime - return NextResponse.next(); -} +import { NextResponse } from 'next/server'; + +export function middleware() { + // Basic middleware to ensure that the build works with edge runtime + return NextResponse.next(); +} diff --git a/packages/nextjs/.eslintrc.js b/packages/nextjs/.eslintrc.js index d255f74ce829..1f0ae547d4e0 100644 --- a/packages/nextjs/.eslintrc.js +++ b/packages/nextjs/.eslintrc.js @@ -21,5 +21,11 @@ module.exports = { 'import/no-extraneous-dependencies': 'off', }, }, + { + files: ['src/config/polyfills/perf_hooks.js'], + globals: { + globalThis: 'readonly', + }, + }, ], }; diff --git a/packages/nextjs/src/config/types.ts b/packages/nextjs/src/config/types.ts index 1ca5eaa6bab0..55f080fb433e 100644 --- a/packages/nextjs/src/config/types.ts +++ b/packages/nextjs/src/config/types.ts @@ -581,6 +581,7 @@ export type BuildContext = { webpack: { version: string; DefinePlugin: new (values: Record) => WebpackPluginInstance; + ProvidePlugin: new (values: Record) => WebpackPluginInstance; }; // eslint-disable-next-line @typescript-eslint/no-explicit-any defaultLoaders: any; // needed for type tests (test:types) diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 68658de4ada7..717559509bdd 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -871,13 +871,10 @@ function addOtelWarningIgnoreRule(newConfig: WebpackConfigObjectWithModuleRules) } function addEdgeRuntimePolyfills(newConfig: WebpackConfigObjectWithModuleRules, buildContext: BuildContext): void { - const { webpack } = buildContext; - // Use ProvidePlugin to inject performance global only when accessed newConfig.plugins = newConfig.plugins || []; newConfig.plugins.push( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - new (webpack as any).ProvidePlugin({ + new buildContext.webpack.ProvidePlugin({ performance: [path.resolve(__dirname, 'polyfills', 'perf_hooks.js'), 'performance'], }), ); diff --git a/packages/nextjs/test/config/fixtures.ts b/packages/nextjs/test/config/fixtures.ts index a3c4feb0123b..5f5d4a2d3504 100644 --- a/packages/nextjs/test/config/fixtures.ts +++ b/packages/nextjs/test/config/fixtures.ts @@ -99,7 +99,13 @@ export function getBuildContext( distDir: '.next', ...materializedNextConfig, } as NextConfigObject, - webpack: { version: webpackVersion, DefinePlugin: class {} as any }, + webpack: { + version: webpackVersion, + DefinePlugin: class {} as any, + ProvidePlugin: class { + constructor(public definitions: Record) {} + } as any, + }, defaultLoaders: true, totalPages: 2, isServer: buildTarget === 'server' || buildTarget === 'edge', diff --git a/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts b/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts index 3a8e86b94e29..d85fbb54ceb0 100644 --- a/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts +++ b/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts @@ -7,6 +7,7 @@ import { CLIENT_SDK_CONFIG_FILE, clientBuildContext, clientWebpackConfig, + edgeBuildContext, exportedNextConfig, serverBuildContext, serverWebpackConfig, @@ -185,4 +186,53 @@ describe('constructWebpackConfigFunction()', () => { }); }); }); + + describe('edge runtime polyfills', () => { + it('adds polyfills only for edge runtime in dev mode', async () => { + // Test edge runtime in dev mode - should add polyfills + const edgeDevBuildContext = { ...edgeBuildContext, dev: true }; + const edgeDevConfig = await materializeFinalWebpackConfig({ + exportedNextConfig, + incomingWebpackConfig: serverWebpackConfig, + incomingWebpackBuildContext: edgeDevBuildContext, + }); + + const edgeProvidePlugin = edgeDevConfig.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin'); + expect(edgeProvidePlugin).toBeDefined(); + expect(edgeDevConfig.resolve?.alias?.perf_hooks).toMatch(/perf_hooks\.js$/); + + // Test edge runtime in prod mode - should NOT add polyfills + const edgeProdBuildContext = { ...edgeBuildContext, dev: false }; + const edgeProdConfig = await materializeFinalWebpackConfig({ + exportedNextConfig, + incomingWebpackConfig: serverWebpackConfig, + incomingWebpackBuildContext: edgeProdBuildContext, + }); + + const edgeProdProvidePlugin = edgeProdConfig.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin'); + expect(edgeProdProvidePlugin).toBeUndefined(); + + // Test server runtime in dev mode - should NOT add polyfills + const serverDevBuildContext = { ...serverBuildContext, dev: true }; + const serverDevConfig = await materializeFinalWebpackConfig({ + exportedNextConfig, + incomingWebpackConfig: serverWebpackConfig, + incomingWebpackBuildContext: serverDevBuildContext, + }); + + const serverProvidePlugin = serverDevConfig.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin'); + expect(serverProvidePlugin).toBeUndefined(); + + // Test client runtime in dev mode - should NOT add polyfills + const clientDevBuildContext = { ...clientBuildContext, dev: true }; + const clientDevConfig = await materializeFinalWebpackConfig({ + exportedNextConfig, + incomingWebpackConfig: clientWebpackConfig, + incomingWebpackBuildContext: clientDevBuildContext, + }); + + const clientProvidePlugin = clientDevConfig.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin'); + expect(clientProvidePlugin).toBeUndefined(); + }); + }); }); From 5202ba6432a156609f2c65b0e0879603b03e809d Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Thu, 11 Sep 2025 13:54:11 +0200 Subject: [PATCH 5/7] Apply polyfill only for nextjs 13 --- packages/nextjs/src/config/webpack.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 717559509bdd..f2c55430e882 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -60,6 +60,8 @@ export function constructWebpackConfigFunction( const pageExtensions = userNextConfig.pageExtensions || ['tsx', 'ts', 'jsx', 'js']; const dotPrefixedPageExtensions = pageExtensions.map(ext => `.${ext}`); const pageExtensionRegex = pageExtensions.map(escapeStringForRegex).join('|'); + const nextJsVersion = getNextjsVersion(); + const { major } = parseSemver(nextJsVersion || ''); // We add `.ts` and `.js` back in because `pageExtensions` might not be relevant to the instrumentation file // e.g. user's setting `.mdx`. In that case we still want to default look up @@ -70,8 +72,6 @@ export function constructWebpackConfigFunction( warnAboutDeprecatedConfigFiles(projectDir, instrumentationFile, runtime); } if (runtime === 'server') { - const nextJsVersion = getNextjsVersion(); - const { major } = parseSemver(nextJsVersion || ''); // was added in v15 (https://github.com/vercel/next.js/pull/67539) if (major && major >= 15) { warnAboutMissingOnRequestErrorHandler(instrumentationFile); @@ -104,7 +104,7 @@ export function constructWebpackConfigFunction( addOtelWarningIgnoreRule(newConfig); // Add edge runtime polyfills when building for edge in dev mode - if (runtime === 'edge' && isDev) { + if (major && major === 13 && runtime === 'edge' && isDev) { addEdgeRuntimePolyfills(newConfig, buildContext); } From 5250cbab931e18866bd23a6f9dea54d4458a1a2a Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Thu, 11 Sep 2025 15:22:07 +0200 Subject: [PATCH 6/7] Account for timeOrigin --- packages/nextjs/src/config/polyfills/perf_hooks.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/nextjs/src/config/polyfills/perf_hooks.js b/packages/nextjs/src/config/polyfills/perf_hooks.js index fe0c5b84657a..1a0ce4a2af76 100644 --- a/packages/nextjs/src/config/polyfills/perf_hooks.js +++ b/packages/nextjs/src/config/polyfills/perf_hooks.js @@ -1,21 +1,22 @@ // Polyfill for Node.js perf_hooks module in edge runtime // This mirrors the polyfill from packages/vercel-edge/rollup.npm.config.mjs +const __sentry__timeOrigin = Date.now(); // Ensure performance global is available if (typeof globalThis !== 'undefined' && globalThis.performance === undefined) { globalThis.performance = { - timeOrigin: 0, + timeOrigin: __sentry__timeOrigin, now: function () { - return Date.now(); + return Date.now() - __sentry__timeOrigin; }, }; } // Export the performance object for perf_hooks compatibility export const performance = globalThis.performance || { - timeOrigin: 0, + timeOrigin: __sentry__timeOrigin, now: function () { - return Date.now(); + return Date.now() - __sentry__timeOrigin; }, }; From 4b8db28fab59126b57704f20612be44d213296b1 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Thu, 11 Sep 2025 15:59:08 +0200 Subject: [PATCH 7/7] Add tests for nextjs 13 checks --- packages/nextjs/src/config/webpack.ts | 4 +- .../webpack/constructWebpackConfig.test.ts | 75 ++++++++++++++++++- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index f2c55430e882..8741efe81194 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -60,8 +60,8 @@ export function constructWebpackConfigFunction( const pageExtensions = userNextConfig.pageExtensions || ['tsx', 'ts', 'jsx', 'js']; const dotPrefixedPageExtensions = pageExtensions.map(ext => `.${ext}`); const pageExtensionRegex = pageExtensions.map(escapeStringForRegex).join('|'); - const nextJsVersion = getNextjsVersion(); - const { major } = parseSemver(nextJsVersion || ''); + const nextVersion = nextJsVersion || getNextjsVersion(); + const { major } = parseSemver(nextVersion || ''); // We add `.ts` and `.js` back in because `pageExtensions` might not be relevant to the instrumentation file // e.g. user's setting `.mdx`. In that case we still want to default look up diff --git a/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts b/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts index d85fbb54ceb0..7371d35c859a 100644 --- a/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts +++ b/packages/nextjs/test/config/webpack/constructWebpackConfig.test.ts @@ -2,6 +2,7 @@ import '../mocks'; import * as core from '@sentry/core'; import { describe, expect, it, vi } from 'vitest'; +import * as util from '../../../src/config/util'; import * as getWebpackPluginOptionsModule from '../../../src/config/webpackPluginOptions'; import { CLIENT_SDK_CONFIG_FILE, @@ -188,8 +189,11 @@ describe('constructWebpackConfigFunction()', () => { }); describe('edge runtime polyfills', () => { - it('adds polyfills only for edge runtime in dev mode', async () => { - // Test edge runtime in dev mode - should add polyfills + it('adds polyfills only for edge runtime in dev mode on Next.js 13', async () => { + // Mock Next.js version 13 - polyfills should be added + vi.spyOn(util, 'getNextjsVersion').mockReturnValue('13.0.0'); + + // Test edge runtime in dev mode with Next.js 13 - should add polyfills const edgeDevBuildContext = { ...edgeBuildContext, dev: true }; const edgeDevConfig = await materializeFinalWebpackConfig({ exportedNextConfig, @@ -201,6 +205,13 @@ describe('constructWebpackConfigFunction()', () => { expect(edgeProvidePlugin).toBeDefined(); expect(edgeDevConfig.resolve?.alias?.perf_hooks).toMatch(/perf_hooks\.js$/); + vi.restoreAllMocks(); + }); + + it('does NOT add polyfills for edge runtime in prod mode even on Next.js 13', async () => { + // Mock Next.js version 13 - but prod mode should still not add polyfills + vi.spyOn(util, 'getNextjsVersion').mockReturnValue('13.0.0'); + // Test edge runtime in prod mode - should NOT add polyfills const edgeProdBuildContext = { ...edgeBuildContext, dev: false }; const edgeProdConfig = await materializeFinalWebpackConfig({ @@ -212,6 +223,13 @@ describe('constructWebpackConfigFunction()', () => { const edgeProdProvidePlugin = edgeProdConfig.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin'); expect(edgeProdProvidePlugin).toBeUndefined(); + vi.restoreAllMocks(); + }); + + it('does NOT add polyfills for server runtime even on Next.js 13', async () => { + // Mock Next.js version 13 + vi.spyOn(util, 'getNextjsVersion').mockReturnValue('13.0.0'); + // Test server runtime in dev mode - should NOT add polyfills const serverDevBuildContext = { ...serverBuildContext, dev: true }; const serverDevConfig = await materializeFinalWebpackConfig({ @@ -223,6 +241,13 @@ describe('constructWebpackConfigFunction()', () => { const serverProvidePlugin = serverDevConfig.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin'); expect(serverProvidePlugin).toBeUndefined(); + vi.restoreAllMocks(); + }); + + it('does NOT add polyfills for client runtime even on Next.js 13', async () => { + // Mock Next.js version 13 + vi.spyOn(util, 'getNextjsVersion').mockReturnValue('13.0.0'); + // Test client runtime in dev mode - should NOT add polyfills const clientDevBuildContext = { ...clientBuildContext, dev: true }; const clientDevConfig = await materializeFinalWebpackConfig({ @@ -233,6 +258,52 @@ describe('constructWebpackConfigFunction()', () => { const clientProvidePlugin = clientDevConfig.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin'); expect(clientProvidePlugin).toBeUndefined(); + + vi.restoreAllMocks(); + }); + + it('does NOT add polyfills for edge runtime in dev mode on Next.js versions other than 13', async () => { + const edgeDevBuildContext = { ...edgeBuildContext, dev: true }; + + // Test with Next.js 12 - should NOT add polyfills + vi.spyOn(util, 'getNextjsVersion').mockReturnValue('12.3.0'); + const edgeConfigV12 = await materializeFinalWebpackConfig({ + exportedNextConfig, + incomingWebpackConfig: serverWebpackConfig, + incomingWebpackBuildContext: edgeDevBuildContext, + }); + expect(edgeConfigV12.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin')).toBeUndefined(); + vi.restoreAllMocks(); + + // Test with Next.js 14 - should NOT add polyfills + vi.spyOn(util, 'getNextjsVersion').mockReturnValue('14.0.0'); + const edgeConfigV14 = await materializeFinalWebpackConfig({ + exportedNextConfig, + incomingWebpackConfig: serverWebpackConfig, + incomingWebpackBuildContext: edgeDevBuildContext, + }); + expect(edgeConfigV14.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin')).toBeUndefined(); + vi.restoreAllMocks(); + + // Test with Next.js 15 - should NOT add polyfills + vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.0.0'); + const edgeConfigV15 = await materializeFinalWebpackConfig({ + exportedNextConfig, + incomingWebpackConfig: serverWebpackConfig, + incomingWebpackBuildContext: edgeDevBuildContext, + }); + expect(edgeConfigV15.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin')).toBeUndefined(); + vi.restoreAllMocks(); + + // Test with undefined Next.js version - should NOT add polyfills + vi.spyOn(util, 'getNextjsVersion').mockReturnValue(undefined); + const edgeConfigUndefined = await materializeFinalWebpackConfig({ + exportedNextConfig, + incomingWebpackConfig: serverWebpackConfig, + incomingWebpackBuildContext: edgeDevBuildContext, + }); + expect(edgeConfigUndefined.plugins?.find(plugin => plugin.constructor.name === 'ProvidePlugin')).toBeUndefined(); + vi.restoreAllMocks(); }); }); });