diff --git a/packages/nextjs/src/config/webpackPluginOptions.ts b/packages/nextjs/src/config/webpackPluginOptions.ts index 1bca9bff49b6..7b183047896a 100644 --- a/packages/nextjs/src/config/webpackPluginOptions.ts +++ b/packages/nextjs/src/config/webpackPluginOptions.ts @@ -11,37 +11,43 @@ export function getWebpackPluginOptions( buildContext: BuildContext, sentryBuildOptions: SentryBuildOptions, ): SentryWebpackPluginOptions { - const { buildId, isServer, config: userNextConfig, dir: projectDir, nextRuntime } = buildContext; + const { buildId, isServer, config: userNextConfig, dir, nextRuntime } = buildContext; const prefixInsert = !isServer ? 'Client' : nextRuntime === 'edge' ? 'Edge' : 'Node.js'; - const distDirAbsPath = path.join(projectDir, (userNextConfig as NextConfigObject).distDir || '.next'); // `.next` is the default directory + // We need to convert paths to posix because Glob patterns use `\` to escape + // glob characters. This clashes with Windows path separators. + // See: https://www.npmjs.com/package/glob + const projectDir = dir.replace(/\\/g, '/'); + // `.next` is the default directory + const distDir = (userNextConfig as NextConfigObject).distDir?.replace(/\\/g, '/') ?? '.next'; + const distDirAbsPath = path.posix.join(projectDir, distDir); let sourcemapUploadAssets: string[] = []; const sourcemapUploadIgnore: string[] = []; if (isServer) { sourcemapUploadAssets.push( - path.join(distDirAbsPath, 'server', '**'), // This is normally where Next.js outputs things - path.join(distDirAbsPath, 'serverless', '**'), // This was the output location for serverless Next.js + path.posix.join(distDirAbsPath, 'server', '**'), // This is normally where Next.js outputs things + path.posix.join(distDirAbsPath, 'serverless', '**'), // This was the output location for serverless Next.js ); } else { if (sentryBuildOptions.widenClientFileUpload) { - sourcemapUploadAssets.push(path.join(distDirAbsPath, 'static', 'chunks', '**')); + sourcemapUploadAssets.push(path.posix.join(distDirAbsPath, 'static', 'chunks', '**')); } else { sourcemapUploadAssets.push( - path.join(distDirAbsPath, 'static', 'chunks', 'pages', '**'), - path.join(distDirAbsPath, 'static', 'chunks', 'app', '**'), + path.posix.join(distDirAbsPath, 'static', 'chunks', 'pages', '**'), + path.posix.join(distDirAbsPath, 'static', 'chunks', 'app', '**'), ); } // TODO: We should think about uploading these when `widenClientFileUpload` is `true`. They may be useful in some situations. sourcemapUploadIgnore.push( - path.join(distDirAbsPath, 'static', 'chunks', 'framework-*'), - path.join(distDirAbsPath, 'static', 'chunks', 'framework.*'), - path.join(distDirAbsPath, 'static', 'chunks', 'main-*'), - path.join(distDirAbsPath, 'static', 'chunks', 'polyfills-*'), - path.join(distDirAbsPath, 'static', 'chunks', 'webpack-*'), + path.posix.join(distDirAbsPath, 'static', 'chunks', 'framework-*'), + path.posix.join(distDirAbsPath, 'static', 'chunks', 'framework.*'), + path.posix.join(distDirAbsPath, 'static', 'chunks', 'main-*'), + path.posix.join(distDirAbsPath, 'static', 'chunks', 'polyfills-*'), + path.posix.join(distDirAbsPath, 'static', 'chunks', 'webpack-*'), ); } @@ -79,9 +85,9 @@ export function getWebpackPluginOptions( // We only care to delete client bundle source maps because they would be the ones being served. // Removing the server source maps crashes Vercel builds for (thus far) unknown reasons: // https://github.com/getsentry/sentry-javascript/issues/13099 - path.join(distDirAbsPath, 'static', '**', '*.js.map'), - path.join(distDirAbsPath, 'static', '**', '*.mjs.map'), - path.join(distDirAbsPath, 'static', '**', '*.cjs.map'), + path.posix.join(distDirAbsPath, 'static', '**', '*.js.map'), + path.posix.join(distDirAbsPath, 'static', '**', '*.mjs.map'), + path.posix.join(distDirAbsPath, 'static', '**', '*.cjs.map'), ] : undefined, ...sentryBuildOptions.unstable_sentryWebpackPluginOptions?.sourcemaps, diff --git a/packages/nextjs/test/config/webpack/webpackPluginOptions.test.ts b/packages/nextjs/test/config/webpack/webpackPluginOptions.test.ts index 557859b2a7e1..177077d2b5c4 100644 --- a/packages/nextjs/test/config/webpack/webpackPluginOptions.test.ts +++ b/packages/nextjs/test/config/webpack/webpackPluginOptions.test.ts @@ -2,6 +2,7 @@ import type { BuildContext, NextConfigObject } from '../../../src/config/types'; import { getWebpackPluginOptions } from '../../../src/config/webpackPluginOptions'; function generateBuildContext(overrides: { + dir?: string; isServer: boolean; nextjsConfig?: NextConfigObject; }): BuildContext { @@ -9,7 +10,7 @@ function generateBuildContext(overrides: { dev: false, // The plugin is not included in dev mode isServer: overrides.isServer, buildId: 'test-build-id', - dir: '/my/project/dir', + dir: overrides.dir ?? '/my/project/dir', config: overrides.nextjsConfig ?? {}, totalPages: 2, defaultLoaders: true, @@ -171,4 +172,23 @@ describe('getWebpackPluginOptions()', () => { assets: [], }); }); + + it('passes posix paths to the plugin', () => { + const buildContext = generateBuildContext({ + dir: 'C:\\my\\windows\\project\\dir', + nextjsConfig: { distDir: '.dist\\v1' }, + isServer: false, + }); + const generatedPluginOptions = getWebpackPluginOptions(buildContext, { widenClientFileUpload: true }); + expect(generatedPluginOptions.sourcemaps).toMatchObject({ + assets: ['C:/my/windows/project/dir/.dist/v1/static/chunks/**'], + ignore: [ + 'C:/my/windows/project/dir/.dist/v1/static/chunks/framework-*', + 'C:/my/windows/project/dir/.dist/v1/static/chunks/framework.*', + 'C:/my/windows/project/dir/.dist/v1/static/chunks/main-*', + 'C:/my/windows/project/dir/.dist/v1/static/chunks/polyfills-*', + 'C:/my/windows/project/dir/.dist/v1/static/chunks/webpack-*', + ], + }); + }); });