Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nextjs): Add distDirOverride #6194

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/nextjs/src/config/types.ts
Expand Up @@ -59,6 +59,14 @@ export type UserSentryOptions = {

// Automatically instrument Next.js data fetching methods and Next.js API routes
autoInstrumentServerFunctions?: boolean;

// Override the distDir which is helpful if the if you're using a monorepo, such as Nx.
// Ultimately, directs the Sentry CLI to the correct directory.
// Monorepo example:
// App Directory: `apps/my-next-app`
// NextJS `distDir` is set to`../../dist/apps/my-next-app/.next`.
// Sentry `distDirOverride` should be set to `dist/apps/my-next-app/.next`, as the CLI is run from the monorepo root.
distDirOverride?: string;
};

export type NextConfigFunction = (phase: string, defaults: { defaultConfig: NextConfigObject }) => NextConfigObject;
Expand Down
2 changes: 1 addition & 1 deletion packages/nextjs/src/config/webpack.ts
Expand Up @@ -403,7 +403,7 @@ export function getWebpackPluginOptions(
const { buildId, isServer, webpack, config, dev: isDev, dir: projectDir } = buildContext;
const userNextConfig = config as NextConfigObject;

const distDir = userNextConfig.distDir ?? '.next'; // `.next` is the default directory
const distDir = userSentryOptions.distDirOverride ?? userNextConfig.distDir ?? '.next'; // `.next` is the default directory

const isWebpack5 = webpack.version.startsWith('5');
const isServerless = userNextConfig.target === 'experimental-serverless-trace';
Expand Down
69 changes: 69 additions & 0 deletions packages/nextjs/test/config/webpack/sentryWebpackPlugin.test.ts
Expand Up @@ -99,6 +99,27 @@ describe('Sentry webpack plugin config', () => {
]);
});

it('has the correct value when building client bundles using `distDirOverride` option', async () => {
const exportedNextConfigWithDistDirOverride = {
...exportedNextConfig,
sentry: { distDirOverride: 'dist/.next' },
};
const finalWebpackConfig = await materializeFinalWebpackConfig({
exportedNextConfig: exportedNextConfigWithDistDirOverride,
incomingWebpackConfig: clientWebpackConfig,
incomingWebpackBuildContext: getBuildContext('client', exportedNextConfigWithDistDirOverride),
});

const sentryWebpackPluginInstance = findWebpackPlugin(
finalWebpackConfig,
'SentryCliPlugin',
) as SentryWebpackPlugin;

expect(sentryWebpackPluginInstance.options.include).toEqual([
{ paths: ['dist/.next/static/chunks/pages'], urlPrefix: '~/_next/static/chunks/pages' },
]);
});

it('has the correct value when building serverless server bundles', async () => {
const exportedNextConfigServerless = {
...exportedNextConfig,
Expand Down Expand Up @@ -474,4 +495,52 @@ describe('Sentry webpack plugin config', () => {
}
});
});

describe('correct paths from `distDirOverride` in WebpackPluginOptions', () => {
const customDistDir = 'tmpDir';
const defaultDistDir = '.next';
const expectedDistDir = 'dist/.next';

it.each([
getBuildContext('client', {}),
getBuildContext('server', { target: 'experimental-serverless-trace' }), // serverless
getBuildContext('server', {}, '4'),
getBuildContext('server', {}, '5'),
])('`distDir` is not defined', (buildContext: BuildContext) => {
const includePaths = getWebpackPluginOptions(
buildContext,
{}, // userPluginOptions
{ distDirOverride: expectedDistDir }, // userSentryOptions
).include as { paths: [] }[];

expect(buildContext.config.distDir).toEqual(defaultDistDir);

for (const pathDescriptor of includePaths) {
for (const path of pathDescriptor.paths) {
expect(path).toMatch(new RegExp(`^${expectedDistDir}.*`));
}
}
});

it.each([
getBuildContext('client', { distDir: customDistDir }),
getBuildContext('server', { distDir: customDistDir, target: 'experimental-serverless-trace' }), // serverless
getBuildContext('server', { distDir: customDistDir }, '4'),
getBuildContext('server', { distDir: customDistDir }, '5'),
])('`distDir` is defined', (buildContext: BuildContext) => {
const includePaths = getWebpackPluginOptions(
buildContext,
{}, // userPluginOptions
{ distDirOverride: expectedDistDir }, // userSentryOptions
).include as { paths: [] }[];

expect(buildContext.config.distDir).toEqual(customDistDir);

for (const pathDescriptor of includePaths) {
for (const path of pathDescriptor.paths) {
expect(path).toMatch(new RegExp(`^${expectedDistDir}.*`));
}
}
});
});
});