Skip to content

Commit d7c6e9d

Browse files
committed
fix(nextjs): handle assetPrefix
1 parent 5be5a04 commit d7c6e9d

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

packages/nextjs/src/config/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export type NextConfigObject = {
3030
distDir?: string;
3131
// The root at which the nextjs app will be served (defaults to "/")
3232
basePath?: string;
33+
// The asset prefix (pathname or full URL) if assets will not be stored at the default Next.js location
34+
assetPrefix?: string;
3335
// Config which will be available at runtime
3436
publicRuntimeConfig?: { [key: string]: unknown };
3537
// File extensions that count as pages in the `pages/` directory

packages/nextjs/src/config/webpack.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { default as SentryWebpackPlugin } from '@sentry/webpack-plugin';
55
import * as chalk from 'chalk';
66
import * as fs from 'fs';
77
import * as path from 'path';
8+
import * as url from 'url';
89

910
import {
1011
BuildContext,
@@ -457,7 +458,14 @@ export function getWebpackPluginOptions(
457458
const isWebpack5 = webpack.version.startsWith('5');
458459
const isServerless = userNextConfig.target === 'experimental-serverless-trace';
459460
const hasSentryProperties = fs.existsSync(path.resolve(projectDir, 'sentry.properties'));
460-
const urlPrefix = userNextConfig.basePath ? `~${userNextConfig.basePath}/_next` : '~/_next';
461+
462+
let assetPrefix = userNextConfig.assetPrefix || userNextConfig.basePath || '';
463+
if (assetPrefix) {
464+
const assertPrefixUrl = url.parse(assetPrefix);
465+
assetPrefix = assertPrefixUrl.pathname || '';
466+
assetPrefix = assetPrefix.endsWith('/') ? assetPrefix.slice(0, -1) : assetPrefix;
467+
}
468+
const urlPrefix = `~${assetPrefix}/_next`;
461469

462470
const serverInclude = isServerless
463471
? [{ paths: [`${distDirAbsPath}/serverless/`], urlPrefix: `${urlPrefix}/serverless` }]

packages/nextjs/test/config/webpack/sentryWebpackPlugin.test.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,89 @@ describe('Sentry webpack plugin config', () => {
295295
});
296296
});
297297

298+
describe('Sentry webpack plugin `urlPrefix` option with assetPrefix set', () => {
299+
it('has the correct value given a path', async () => {
300+
const exportedNextConfigWithAssetPrefix = {
301+
...exportedNextConfig,
302+
assetPrefix: '/asset-prefix',
303+
};
304+
const buildContext = getBuildContext('client', exportedNextConfigWithAssetPrefix);
305+
const finalWebpackConfig = await materializeFinalWebpackConfig({
306+
exportedNextConfig: exportedNextConfigWithAssetPrefix,
307+
incomingWebpackConfig: clientWebpackConfig,
308+
incomingWebpackBuildContext: buildContext,
309+
});
310+
311+
const sentryWebpackPluginInstance = findWebpackPlugin(
312+
finalWebpackConfig,
313+
'SentryCliPlugin',
314+
) as SentryWebpackPlugin;
315+
316+
expect(sentryWebpackPluginInstance.options.urlPrefix).toEqual('~/asset-prefix/_next');
317+
});
318+
319+
it('has the correct value given a path with a leading slash', async () => {
320+
const exportedNextConfigWithAssetPrefix = {
321+
...exportedNextConfig,
322+
assetPrefix: '/asset-prefix/',
323+
};
324+
const buildContext = getBuildContext('client', exportedNextConfigWithAssetPrefix);
325+
const finalWebpackConfig = await materializeFinalWebpackConfig({
326+
exportedNextConfig: exportedNextConfigWithAssetPrefix,
327+
incomingWebpackConfig: clientWebpackConfig,
328+
incomingWebpackBuildContext: buildContext,
329+
});
330+
331+
const sentryWebpackPluginInstance = findWebpackPlugin(
332+
finalWebpackConfig,
333+
'SentryCliPlugin',
334+
) as SentryWebpackPlugin;
335+
336+
expect(sentryWebpackPluginInstance.options.urlPrefix).toEqual('~/asset-prefix/_next');
337+
});
338+
339+
it('has the correct value when given a full URL', async () => {
340+
const exportedNextConfigWithAssetPrefix = {
341+
...exportedNextConfig,
342+
assetPrefix: 'https://cdn.mydomain.com/asset-prefix',
343+
};
344+
const buildContext = getBuildContext('client', exportedNextConfigWithAssetPrefix);
345+
const finalWebpackConfig = await materializeFinalWebpackConfig({
346+
exportedNextConfig: exportedNextConfigWithAssetPrefix,
347+
incomingWebpackConfig: clientWebpackConfig,
348+
incomingWebpackBuildContext: buildContext,
349+
});
350+
351+
const sentryWebpackPluginInstance = findWebpackPlugin(
352+
finalWebpackConfig,
353+
'SentryCliPlugin',
354+
) as SentryWebpackPlugin;
355+
356+
expect(sentryWebpackPluginInstance.options.urlPrefix).toEqual('~/asset-prefix/_next');
357+
});
358+
359+
it('takes priority over basePath ', async () => {
360+
const exportedNextConfigWithAssetPrefix = {
361+
...exportedNextConfig,
362+
assetPrefix: '/asset-prefix',
363+
basePath: '/base-path',
364+
};
365+
const buildContext = getBuildContext('client', exportedNextConfigWithAssetPrefix);
366+
const finalWebpackConfig = await materializeFinalWebpackConfig({
367+
exportedNextConfig: exportedNextConfigWithAssetPrefix,
368+
incomingWebpackConfig: clientWebpackConfig,
369+
incomingWebpackBuildContext: buildContext,
370+
});
371+
372+
const sentryWebpackPluginInstance = findWebpackPlugin(
373+
finalWebpackConfig,
374+
'SentryCliPlugin',
375+
) as SentryWebpackPlugin;
376+
377+
expect(sentryWebpackPluginInstance.options.urlPrefix).toEqual('~/asset-prefix/_next');
378+
});
379+
});
380+
298381
describe('SentryWebpackPlugin enablement', () => {
299382
let processEnvBackup: typeof process.env;
300383

0 commit comments

Comments
 (0)