Skip to content

Commit 4c0d008

Browse files
committed
add valueinjection to turbopack
1 parent f9430fe commit 4c0d008

File tree

5 files changed

+551
-7
lines changed

5 files changed

+551
-7
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import * as path from 'path';
2+
import type { RouteManifest } from '../manifest/types';
3+
import type {
4+
NextConfigObject,
5+
SentryBuildOptions,
6+
TurbopackOptions,
7+
TurbopackRuleConfigItemOrShortcut,
8+
} from '../types';
9+
10+
/**
11+
* Construct a Turbopack config object from a Next.js config object and a Turbopack options object.
12+
*
13+
* @param nextConfig - The Next.js config object.
14+
* @param turbopackOptions - The Turbopack options object.
15+
* @returns The Turbopack config object.
16+
*/
17+
export function constructTurbopackConfig({
18+
userNextConfig,
19+
manifest,
20+
}: {
21+
userNextConfig: NextConfigObject;
22+
userSentryOptions: SentryBuildOptions;
23+
manifest?: RouteManifest;
24+
}): TurbopackOptions {
25+
const newConfig: TurbopackOptions = {
26+
...userNextConfig.turbopack,
27+
};
28+
29+
if (manifest) {
30+
newConfig.rules = safelyAddTurbopackRule(newConfig.rules, {
31+
matcher: '**/instrumentation-client.*',
32+
rule: {
33+
loaders: [
34+
{
35+
loader: path.resolve(__dirname, '../loaders/valueInjectionLoader.js'),
36+
options: {
37+
values: {
38+
_sentryRouteManifest: JSON.stringify(manifest),
39+
},
40+
},
41+
},
42+
],
43+
},
44+
});
45+
}
46+
47+
return newConfig;
48+
}
49+
50+
/**
51+
* Safely add a Turbopack rule to the existing rules.
52+
*
53+
* @param existingRules - The existing rules.
54+
* @param matcher - The matcher for the rule.
55+
* @param rule - The rule to add.
56+
* @returns The updated rules object.
57+
*/
58+
export function safelyAddTurbopackRule(
59+
existingRules: TurbopackOptions['rules'],
60+
{ matcher, rule }: { matcher: string; rule: TurbopackRuleConfigItemOrShortcut },
61+
): TurbopackOptions['rules'] {
62+
if (!existingRules) {
63+
return {
64+
[matcher]: rule,
65+
};
66+
}
67+
68+
// If the rule already exists, we don't want to mess with it.
69+
if (existingRules[matcher]) {
70+
return existingRules;
71+
}
72+
73+
return {
74+
...existingRules,
75+
[matcher]: rule,
76+
};
77+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './constructTurbopackConfig';

packages/nextjs/src/config/types.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export type NextConfigObject = {
5151
// https://nextjs.org/docs/pages/api-reference/next-config-js/env
5252
env?: Record<string, string>;
5353
serverExternalPackages?: string[]; // next >= v15.0.0
54+
turbopack?: TurbopackOptions;
5455
};
5556

5657
export type SentryBuildOptions = {
@@ -596,3 +597,38 @@ export type EnhancedGlobal = typeof GLOBAL_OBJ & {
596597
SENTRY_RELEASE?: { id: string };
597598
SENTRY_RELEASES?: { [key: string]: { id: string } };
598599
};
600+
601+
type JSONValue = string | number | boolean | JSONValue[] | { [k: string]: JSONValue };
602+
603+
type TurbopackLoaderItem =
604+
| string
605+
| {
606+
loader: string;
607+
// At the moment, Turbopack options must be JSON-serializable, so restrict values.
608+
options: Record<string, JSONValue>;
609+
};
610+
611+
type TurbopackRuleCondition = {
612+
path: string | RegExp;
613+
};
614+
615+
export type TurbopackRuleConfigItemOrShortcut = TurbopackLoaderItem[] | TurbopackRuleConfigItem;
616+
617+
type TurbopackRuleConfigItemOptions = {
618+
loaders: TurbopackLoaderItem[];
619+
as?: string;
620+
};
621+
622+
type TurbopackRuleConfigItem =
623+
| TurbopackRuleConfigItemOptions
624+
| { [condition: string]: TurbopackRuleConfigItem }
625+
| false;
626+
627+
export interface TurbopackOptions {
628+
resolveAlias?: Record<string, string | string[] | Record<string, string | string[]>>;
629+
resolveExtensions?: string[];
630+
rules?: Record<string, TurbopackRuleConfigItemOrShortcut>;
631+
conditions?: Record<string, TurbopackRuleCondition>;
632+
moduleIds?: 'named' | 'deterministic';
633+
root?: string;
634+
}

packages/nextjs/src/config/withSentryConfig.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as fs from 'fs';
77
import * as path from 'path';
88
import { createRouteManifest } from './manifest/createRouteManifest';
99
import type { RouteManifest } from './manifest/types';
10+
import { constructTurbopackConfig } from './turbopack';
1011
import type {
1112
ExportedNextConfig as NextConfig,
1213
NextConfigFunction,
@@ -251,6 +252,8 @@ function getFinalConfigObject(
251252
}
252253

253254
let nextMajor: number | undefined;
255+
const isTurbopack = process.env.TURBOPACK;
256+
let isTurbopackSupported = false;
254257
if (nextJsVersion) {
255258
const { major, minor, patch, prerelease } = parseSemver(nextJsVersion);
256259
nextMajor = major;
@@ -262,6 +265,7 @@ function getFinalConfigObject(
262265
(major === 15 && minor > 3) ||
263266
(major === 15 && minor === 3 && patch === 0 && prerelease === undefined) ||
264267
(major === 15 && minor === 3 && patch > 0));
268+
isTurbopackSupported = isSupportedVersion;
265269
const isSupportedCanary =
266270
major !== undefined &&
267271
minor !== undefined &&
@@ -274,7 +278,7 @@ function getFinalConfigObject(
274278
parseInt(prerelease.split('.')[1] || '', 10) >= 28;
275279
const supportsClientInstrumentation = isSupportedCanary || isSupportedVersion;
276280

277-
if (!supportsClientInstrumentation && process.env.TURBOPACK) {
281+
if (!supportsClientInstrumentation && isTurbopack) {
278282
if (process.env.NODE_ENV === 'development') {
279283
// eslint-disable-next-line no-console
280284
console.warn(
@@ -307,12 +311,18 @@ function getFinalConfigObject(
307311
],
308312
},
309313
}),
310-
webpack: constructWebpackConfigFunction(
311-
incomingUserNextConfigObject,
312-
userSentryOptions,
313-
releaseName,
314-
routeManifest,
315-
),
314+
315+
webpack: !isTurbopack
316+
? constructWebpackConfigFunction(incomingUserNextConfigObject, userSentryOptions, releaseName, routeManifest)
317+
: undefined,
318+
turbopack:
319+
isTurbopackSupported && isTurbopack
320+
? constructTurbopackConfig({
321+
userNextConfig: incomingUserNextConfigObject,
322+
userSentryOptions,
323+
manifest: routeManifest,
324+
})
325+
: undefined,
316326
};
317327
}
318328

0 commit comments

Comments
 (0)