Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/nextjs/src/config/getBuildPluginOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,5 +357,8 @@ export function getBuildPluginOptions({
},
},
...sentryBuildOptions.webpack?.unstable_sentryWebpackPluginOptions,
// Only the browser reads these tags (`thirdPartyErrorFilterIntegration`), so server bundles skip the per-module cost.
// Set after the spread so a key passed through `unstable_sentryWebpackPluginOptions` is dropped on the server too.
...(buildTool === 'webpack-nodejs' || buildTool === 'webpack-edge' ? { applicationKey: undefined } : {}),
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,14 @@ export function constructTurbopackConfig({
// so it is safe even for node_modules with strict initialization order.
// We only exclude Next.js build polyfills which contain non-standard syntax that causes
// parse errors when any code is prepended (Turbopack re-parses the loader output).
// Server and edge modules are skipped because only the browser reads these tags.
// eslint-disable-next-line typescript/no-deprecated
const applicationKey = userSentryOptions?.applicationKey ?? userSentryOptions?._experimental?.turbopackApplicationKey;
if (applicationKey && nextJsVersion && supportsTurbopackRuleCondition(nextJsVersion)) {
newConfig.rules = safelyAddTurbopackRule(newConfig.rules, {
matcher: '*.{ts,tsx,js,jsx,mjs,cjs}',
rule: {
condition: { not: { path: /next\/dist\/build\/polyfills/ } },
condition: { all: ['browser', { not: { path: /next\/dist\/build\/polyfills/ } }] },
loaders: [
{
loader: path.resolve(__dirname, '..', 'loaders', 'moduleMetadataInjectionLoader.js'),
Expand Down
25 changes: 25 additions & 0 deletions packages/nextjs/test/config/getBuildPluginOptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,31 @@ describe('getBuildPluginOptions', () => {
expect(result.applicationKey).toBe('my-app-key');
});

it.each(['webpack-nodejs', 'webpack-edge'] as const)('does not forward applicationKey for %s builds', buildTool => {
const result = getBuildPluginOptions({
sentryBuildOptions: { applicationKey: 'my-app-key' },
releaseName: mockReleaseName,
distDirAbsPath: mockDistDirAbsPath,
buildTool,
});

expect(result.applicationKey).toBeUndefined();
});

it.each(['webpack-nodejs', 'webpack-edge'] as const)(
'does not forward applicationKey from unstable_sentryWebpackPluginOptions for %s builds',
buildTool => {
const result = getBuildPluginOptions({
sentryBuildOptions: { webpack: { unstable_sentryWebpackPluginOptions: { applicationKey: 'my-app-key' } } },
releaseName: mockReleaseName,
distDirAbsPath: mockDistDirAbsPath,
buildTool,
});

expect(result.applicationKey).toBeUndefined();
},
);

it('normalizes Windows paths to posix for glob patterns in after-production-compile builds', () => {
const windowsPath = 'C:\\Users\\test\\.next';
const sentryBuildOptions: SentryBuildOptions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ describe('moduleMetadataInjection with applicationKey', () => {
});

expect(result.rules!['*.{ts,tsx,js,jsx,mjs,cjs}']).toEqual({
condition: { not: { path: /next\/dist\/build\/polyfills/ } },
condition: { all: ['browser', { not: { path: /next\/dist\/build\/polyfills/ } }] },
loaders: [
{
loader: '/mocked/path/to/moduleMetadataInjectionLoader.js',
Expand Down Expand Up @@ -1010,7 +1010,7 @@ describe('moduleMetadataInjection with applicationKey', () => {
expect(rule.loaders[0]!.options.applicationKey).toBe('top-level-key');
});

it('should only exclude Next.js polyfills, not all foreign modules', () => {
it('should only tag browser modules and exclude Next.js polyfills, not all foreign modules', () => {
const userNextConfig: NextConfigObject = {};

const result = constructTurbopackConfig({
Expand All @@ -1019,11 +1019,11 @@ describe('moduleMetadataInjection with applicationKey', () => {
nextJsVersion: '16.0.0',
});

const rule = result.rules!['*.{ts,tsx,js,jsx,mjs,cjs}'] as { condition?: { not: unknown }; loaders: unknown[] };
const rule = result.rules!['*.{ts,tsx,js,jsx,mjs,cjs}'] as { condition?: unknown; loaders: unknown[] };
// Unlike component annotation (which uses { not: 'foreign' }), metadata injection
// must cover node_modules to match the webpack plugin's BannerPlugin behavior.
// Only Next.js build polyfills are excluded because they have non-standard syntax.
expect(rule.condition).toEqual({ not: { path: /next\/dist\/build\/polyfills/ } });
expect(rule.condition).toEqual({ all: ['browser', { not: { path: /next\/dist\/build\/polyfills/ } }] });
});

it('should NOT add metadata loader rule when Next.js < 16', () => {
Expand Down Expand Up @@ -1118,7 +1118,7 @@ describe('moduleMetadataInjection with applicationKey', () => {
});

expect(result.rules!['*.{ts,tsx,js,jsx,mjs,cjs}']).toEqual({
condition: { not: { path: /next\/dist\/build\/polyfills/ } },
condition: { all: ['browser', { not: { path: /next\/dist\/build\/polyfills/ } }] },
loaders: [
{
loader: '/mocked/path/to/moduleMetadataInjectionLoader.js',
Expand Down
Loading