11import type { Options as SentryBuildPluginOptions } from '@sentry/bundler-plugin-core' ;
22import * as path from 'path' ;
3- import type { SentryBuildOptions } from './types' ;
3+ import type { BuildContext , NextConfigObject , SentryBuildOptions } from './types' ;
44
55/**
6- * Get Sentry Build Plugin options for the runAfterProductionCompile hook.
6+ * Get Sentry Build Plugin options for both webpack and turbopack builds.
7+ * These options can be used in two ways:
8+ * 1. The build can be done in a single operation after the production build completes
9+ * 2. The build can be done in multiple operations, one for each webpack build
710 */
811export function getBuildPluginOptions ( {
912 sentryBuildOptions,
1013 releaseName,
1114 distDirAbsPath,
15+ buildTool,
16+ useRunAfterProductionCompileHook,
1217} : {
1318 sentryBuildOptions : SentryBuildOptions ;
1419 releaseName : string | undefined ;
1520 distDirAbsPath : string ;
21+ buildTool : 'webpack-client' | 'webpack-nodejs' | 'webpack-edge' | 'after-production-compile' ;
22+ useRunAfterProductionCompileHook ?: boolean ; // Whether the user has opted into using the experimental hook
1623} ) : SentryBuildPluginOptions {
1724 const sourcemapUploadAssets : string [ ] = [ ] ;
1825 const sourcemapUploadIgnore : string [ ] = [ ] ;
19-
2026 const filesToDeleteAfterUpload : string [ ] = [ ] ;
2127
2228 // We need to convert paths to posix because Glob patterns use `\` to escape
2329 // glob characters. This clashes with Windows path separators.
2430 // See: https://www.npmjs.com/package/glob
2531 const normalizedDistDirAbsPath = distDirAbsPath . replace ( / \\ / g, '/' ) ;
2632
27- sourcemapUploadAssets . push (
28- path . posix . join ( normalizedDistDirAbsPath , '**' ) , // Next.js build output
29- ) ;
30- if ( sentryBuildOptions . sourcemaps ?. deleteSourcemapsAfterUpload ) {
31- filesToDeleteAfterUpload . push (
32- path . posix . join ( normalizedDistDirAbsPath , '**' , '*.js.map' ) ,
33- path . posix . join ( normalizedDistDirAbsPath , '**' , '*.mjs.map' ) ,
34- path . posix . join ( normalizedDistDirAbsPath , '**' , '*.cjs.map' ) ,
33+ const loggerPrefix = {
34+ 'webpack-nodejs' : '[@sentry/nextjs - Node.js]' ,
35+ 'webpack-edge' : '[@sentry/nextjs - Edge]' ,
36+ 'webpack-client' : '[@sentry/nextjs - Client]' ,
37+ 'after-production-compile' : '[@sentry/nextjs - After Production Compile]' ,
38+ } [ buildTool ] ;
39+
40+ if ( buildTool === 'after-production-compile' ) {
41+ // Turbopack builds
42+ sourcemapUploadAssets . push (
43+ path . posix . join ( normalizedDistDirAbsPath , '**' ) , // Next.js build output
3544 ) ;
45+
46+ if ( sentryBuildOptions . sourcemaps ?. deleteSourcemapsAfterUpload ) {
47+ filesToDeleteAfterUpload . push (
48+ path . posix . join ( normalizedDistDirAbsPath , '**' , '*.js.map' ) ,
49+ path . posix . join ( normalizedDistDirAbsPath , '**' , '*.mjs.map' ) ,
50+ path . posix . join ( normalizedDistDirAbsPath , '**' , '*.cjs.map' ) ,
51+ ) ;
52+ }
53+ } else {
54+ if ( buildTool === 'webpack-nodejs' || buildTool === 'webpack-edge' ) {
55+ sourcemapUploadAssets . push (
56+ path . posix . join ( distDirAbsPath , 'server' , '**' ) , // Standard output location for server builds
57+ path . posix . join ( distDirAbsPath , 'serverless' , '**' ) , // Legacy output location for serverless Next.js
58+ ) ;
59+ } else {
60+ // Client builds
61+ if ( sentryBuildOptions . widenClientFileUpload ) {
62+ sourcemapUploadAssets . push ( path . posix . join ( distDirAbsPath , 'static' , 'chunks' , '**' ) ) ;
63+ } else {
64+ sourcemapUploadAssets . push (
65+ path . posix . join ( distDirAbsPath , 'static' , 'chunks' , 'pages' , '**' ) ,
66+ path . posix . join ( distDirAbsPath , 'static' , 'chunks' , 'app' , '**' ) ,
67+ ) ;
68+ }
69+
70+ // We want to include main-* files if widenClientFileUpload is true as they have proven to be useful
71+ if ( ! sentryBuildOptions . widenClientFileUpload ) {
72+ sourcemapUploadIgnore . push ( path . posix . join ( distDirAbsPath , 'static' , 'chunks' , 'main-*' ) ) ;
73+ }
74+
75+ // Always ignore framework, polyfills, and webpack files
76+ sourcemapUploadIgnore . push (
77+ path . posix . join ( distDirAbsPath , 'static' , 'chunks' , 'framework-*' ) ,
78+ path . posix . join ( distDirAbsPath , 'static' , 'chunks' , 'framework.*' ) ,
79+ path . posix . join ( distDirAbsPath , 'static' , 'chunks' , 'polyfills-*' ) ,
80+ path . posix . join ( distDirAbsPath , 'static' , 'chunks' , 'webpack-*' ) ,
81+ ) ;
82+
83+ // File deletion for webpack client builds
84+ if ( sentryBuildOptions . sourcemaps ?. deleteSourcemapsAfterUpload ) {
85+ filesToDeleteAfterUpload . push (
86+ // We only care to delete client bundle source maps because they would be the ones being served.
87+ // Removing the server source maps crashes Vercel builds for (thus far) unknown reasons:
88+ // https://github.com/getsentry/sentry-javascript/issues/13099
89+ path . posix . join ( distDirAbsPath , 'static' , '**' , '*.js.map' ) ,
90+ path . posix . join ( distDirAbsPath , 'static' , '**' , '*.mjs.map' ) ,
91+ path . posix . join ( distDirAbsPath , 'static' , '**' , '*.cjs.map' ) ,
92+ ) ;
93+ }
94+ }
3695 }
3796
97+ // If the user has opted into using the experimental hook, we skip sourcemaps and release management in the plugin
98+ // to avoid double sourcemap uploads.
99+ const shouldSkipSourcemapsUpload = useRunAfterProductionCompileHook && buildTool . startsWith ( 'webpack' ) ;
100+
38101 return {
39102 authToken : sentryBuildOptions . authToken ,
40103 headers : sentryBuildOptions . headers ,
@@ -43,14 +106,17 @@ export function getBuildPluginOptions({
43106 telemetry : sentryBuildOptions . telemetry ,
44107 debug : sentryBuildOptions . debug ,
45108 errorHandler : sentryBuildOptions . errorHandler ,
46- reactComponentAnnotation : {
47- ...sentryBuildOptions . reactComponentAnnotation ,
48- ...sentryBuildOptions . unstable_sentryWebpackPluginOptions ?. reactComponentAnnotation ,
49- } ,
109+ reactComponentAnnotation :
110+ buildTool === 'after-production-compile'
111+ ? undefined
112+ : {
113+ ...sentryBuildOptions . reactComponentAnnotation ,
114+ ...sentryBuildOptions . unstable_sentryWebpackPluginOptions ?. reactComponentAnnotation ,
115+ } ,
50116 silent : sentryBuildOptions . silent ,
51117 url : sentryBuildOptions . sentryUrl ,
52118 sourcemaps : {
53- disable : sentryBuildOptions . sourcemaps ?. disable ,
119+ disable : sentryBuildOptions . sourcemaps ?. disable || shouldSkipSourcemapsUpload ,
54120 rewriteSources ( source ) {
55121 if ( source . startsWith ( 'webpack://_N_E/' ) ) {
56122 return source . replace ( 'webpack://_N_E/' , '' ) ;
@@ -62,7 +128,7 @@ export function getBuildPluginOptions({
62128 } ,
63129 assets : sentryBuildOptions . sourcemaps ?. assets ?? sourcemapUploadAssets ,
64130 ignore : sentryBuildOptions . sourcemaps ?. ignore ?? sourcemapUploadIgnore ,
65- filesToDeleteAfterUpload,
131+ filesToDeleteAfterUpload : filesToDeleteAfterUpload . length > 0 ? filesToDeleteAfterUpload : undefined ,
66132 ...sentryBuildOptions . unstable_sentryWebpackPluginOptions ?. sourcemaps ,
67133 } ,
68134 release :
@@ -87,11 +153,35 @@ export function getBuildPluginOptions({
87153 ...sentryBuildOptions . bundleSizeOptimizations ,
88154 } ,
89155 _metaOptions : {
90- loggerPrefixOverride : '[@sentry/nextjs]' ,
156+ loggerPrefixOverride : loggerPrefix ,
91157 telemetry : {
92158 metaFramework : 'nextjs' ,
93159 } ,
94160 } ,
95161 ...sentryBuildOptions . unstable_sentryWebpackPluginOptions ,
96162 } ;
97163}
164+
165+ /**
166+ * Legacy function for webpack builds. Now calls the unified getBuildPluginOptions function.
167+ * @deprecated Use getBuildPluginOptions instead
168+ */
169+ export function getWebpackPluginOptions (
170+ buildContext : BuildContext ,
171+ sentryBuildOptions : SentryBuildOptions ,
172+ releaseName : string | undefined ,
173+ ) : SentryBuildPluginOptions {
174+ const { isServer, config : userNextConfig , dir, nextRuntime } = buildContext ;
175+ const buildTool = isServer ? ( nextRuntime === 'edge' ? 'webpack-edge' : 'webpack-nodejs' ) : 'webpack-client' ;
176+
177+ const projectDir = dir . replace ( / \\ / g, '/' ) ;
178+ const distDir = ( userNextConfig as NextConfigObject ) . distDir ?. replace ( / \\ / g, '/' ) ?? '.next' ;
179+ const distDirAbsPath = path . posix . join ( projectDir , distDir ) ;
180+
181+ return getBuildPluginOptions ( {
182+ sentryBuildOptions,
183+ releaseName,
184+ distDirAbsPath,
185+ buildTool,
186+ } ) ;
187+ }
0 commit comments