Skip to content

Commit ff1229b

Browse files
authored
fix(nextjs): Consider pageExtensions option in auto instrumentation (#5881)
1 parent 28c464d commit ff1229b

9 files changed

+65
-4
lines changed

packages/nextjs/src/config/loaders/proxyLoader.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { LoaderThis } from './types';
77

88
type LoaderOptions = {
99
pagesDir: string;
10+
pageExtensionRegex: string;
1011
};
1112

1213
/**
@@ -16,7 +17,7 @@ type LoaderOptions = {
1617
*/
1718
export default async function proxyLoader(this: LoaderThis<LoaderOptions>, userCode: string): Promise<string> {
1819
// We know one or the other will be defined, depending on the version of webpack being used
19-
const { pagesDir } = 'getOptions' in this ? this.getOptions() : this.query;
20+
const { pagesDir, pageExtensionRegex } = 'getOptions' in this ? this.getOptions() : this.query;
2021

2122
// Get the parameterized route name from this page's filepath
2223
const parameterizedRoute = path
@@ -25,7 +26,7 @@ export default async function proxyLoader(this: LoaderThis<LoaderOptions>, userC
2526
// Add a slash at the beginning
2627
.replace(/(.*)/, '/$1')
2728
// Pull off the file extension
28-
.replace(/\.(jsx?|tsx?)/, '')
29+
.replace(new RegExp(`\\.(${pageExtensionRegex})`), '')
2930
// Any page file named `index` corresponds to root of the directory its in, URL-wise, so turn `/xyz/index` into
3031
// just `/xyz`
3132
.replace(/\/index$/, '')

packages/nextjs/src/config/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export type NextConfigObject = {
3232
basePath?: string;
3333
// Config which will be available at runtime
3434
publicRuntimeConfig?: { [key: string]: unknown };
35+
// File extensions that count as pages in the `pages/` directory
36+
pageExtensions?: string[];
3537
};
3638

3739
export type UserSentryOptions = {

packages/nextjs/src/config/webpack.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,17 @@ export function constructWebpackConfigFunction(
8282
if (userSentryOptions.autoInstrumentServerFunctions) {
8383
const pagesDir = newConfig.resolve?.alias?.['private-next-pages'] as string;
8484

85+
// Default page extensions per https://github.com/vercel/next.js/blob/f1dbc9260d48c7995f6c52f8fbcc65f08e627992/packages/next/server/config-shared.ts#L161
86+
const pageExtensions = userNextConfig.pageExtensions || ['tsx', 'ts', 'jsx', 'js'];
87+
const pageExtensionRegex = pageExtensions.map(escapeStringForRegex).join('|');
88+
8589
newConfig.module.rules.push({
8690
// Nextjs allows the `pages` folder to optionally live inside a `src` folder
87-
test: new RegExp(`${escapeStringForRegex(projectDir)}(/src)?/pages/.*\\.(jsx?|tsx?)`),
91+
test: new RegExp(`${escapeStringForRegex(projectDir)}(/src)?/pages/.*\\.(${pageExtensionRegex})`),
8892
use: [
8993
{
9094
loader: path.resolve(__dirname, 'loaders/proxyLoader.js'),
91-
options: { pagesDir },
95+
options: { pagesDir, pageExtensionRegex },
9296
},
9397
],
9498
});

packages/nextjs/test/integration/next.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const moduleExports = {
44
eslint: {
55
ignoreDuringBuilds: true,
66
},
7+
pageExtensions: ['jsx', 'js', 'tsx', 'ts', 'page.tsx'],
78
sentry: {
89
autoInstrumentServerFunctions: true,
910
// Suppress the warning message from `handleSourcemapHidingOptionWarning` in `src/config/webpack.ts`

packages/nextjs/test/integration/next10.config.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const moduleExports = {
55
future: {
66
webpack5: %RUN_WEBPACK_5%,
77
},
8+
pageExtensions: ['jsx', 'js', 'tsx', 'ts', 'page.tsx'],
89
sentry: {
910
autoInstrumentServerFunctions: true,
1011
// Suppress the warning message from `handleSourcemapHidingOptionWarning` in `src/config/webpack.ts`

packages/nextjs/test/integration/next11.config.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const moduleExports = {
66
eslint: {
77
ignoreDuringBuilds: true,
88
},
9+
pageExtensions: ['jsx', 'js', 'tsx', 'ts', 'page.tsx'],
910
sentry: {
1011
autoInstrumentServerFunctions: true,
1112
// Suppress the warning message from `handleSourcemapHidingOptionWarning` in `src/config/webpack.ts`
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const BasicPage = (): JSX.Element => (
2+
<h1>
3+
This page simply exists to test the compatibility of Next.js' `pageExtensions` option with our auto wrapping
4+
process. This file should be turned into a page by Next.js and our webpack loader should process it.
5+
</h1>
6+
);
7+
8+
export async function getServerSideProps() {
9+
return { props: { data: '[some getServerSideProps data]' } };
10+
}
11+
12+
export default BasicPage;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This page simply exists to test the compatibility of Next.js' `pageExtensions` option with our auto wrapping
2+
process. This file should not be turned into a page by Next.js and our webpack loader also shouldn't process it.
3+
This page should not contain valid JavaScript.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
const assert = require('assert');
2+
3+
const { sleep } = require('../utils/common');
4+
const { getAsync, interceptTracingRequest } = require('../utils/server');
5+
6+
module.exports = async ({ url: urlBase, argv }) => {
7+
const url = `${urlBase}/customPageExtension`;
8+
9+
const capturedRequest = interceptTracingRequest(
10+
{
11+
contexts: {
12+
trace: {
13+
op: 'http.server',
14+
status: 'ok',
15+
},
16+
},
17+
transaction: '/customPageExtension',
18+
transaction_info: {
19+
source: 'route',
20+
changes: [],
21+
propagations: 0,
22+
},
23+
type: 'transaction',
24+
request: {
25+
url,
26+
},
27+
},
28+
argv,
29+
'tracingServerGetServerSidePropsCustomPageExtension',
30+
);
31+
32+
await getAsync(url);
33+
await sleep(250);
34+
35+
assert.ok(capturedRequest.isDone(), 'Did not intercept expected request');
36+
};

0 commit comments

Comments
 (0)