Skip to content

Commit fdc07c0

Browse files
author
Hannes Bornö
authored
App files ending with page registred as page files (#42996)
When building (`next/build/index.ts`) files ending with `page.js` got picked up by the RegEx which meant files like `not-a-page.js` ended up as a page. This change makes sure the segment actually starts with `page`. Dev had the same issue and also missed taking `pageExtensions` into account. Fixes #42972 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
1 parent ec07e30 commit fdc07c0

File tree

7 files changed

+26
-14
lines changed

7 files changed

+26
-14
lines changed

packages/next/build/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ export default async function build(
493493
.traceAsyncFn(() =>
494494
recursiveReadDir(
495495
appDir,
496-
new RegExp(`page\\.(?:${config.pageExtensions.join('|')})$`)
496+
new RegExp(`^page\\.(?:${config.pageExtensions.join('|')})$`)
497497
)
498498
)
499499
}

packages/next/server/dev/next-dev-server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ export default class DevServer extends Server {
405405
})
406406

407407
if (isAppPath) {
408-
if (!isLayoutsLeafPage(fileName)) {
408+
if (!isLayoutsLeafPage(fileName, this.nextConfig.pageExtensions)) {
409409
continue
410410
}
411411

packages/next/server/lib/find-page-file.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ export async function findPageFile(
6464
}
6565

6666
// Determine if the file is leaf node page file under layouts,
67-
// The filename should start with 'page', it can be either shared,
68-
// client, or server components with allowed page file extension.
69-
// e.g. page.js, page.server.js, page.client.tsx, etc.
70-
export function isLayoutsLeafPage(filePath: string) {
71-
return /[\\/]?page\.((server|client)\.?)?[jt]sx?$/.test(filePath)
67+
// The filename should start with 'page' and end with one of the allowed extensions
68+
export function isLayoutsLeafPage(filePath: string, pageExtensions: string[]) {
69+
return new RegExp(`(^page|/page)\\.(?:${pageExtensions.join('|')})$`).test(
70+
filePath
71+
)
7272
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function NotAPage() {
2+
return <h1 id="not-a-page">Not a page</h1>
3+
}

test/e2e/app-dir/app/app/catch-all/[...slug]/page.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Widget from './components/widget'
2+
import NotAPage from './not-a-page'
23

34
export default function Page({ params }) {
45
return (
@@ -7,6 +8,7 @@ export default function Page({ params }) {
78
hello from /catch-all/{params.slug.join('/')}
89
</h1>
910
<Widget />
11+
<NotAPage />
1012
</>
1113
)
1214
}

test/e2e/app-dir/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ describe('app dir', () => {
726726
const html = await renderViaHTTP(next.url, `/catch-all/${route}`)
727727
const $ = cheerio.load(html)
728728
expect($('#text').attr('data-params')).toBe(route)
729+
expect($('#not-a-page').text()).toBe('Not a page')
729730

730731
// Components under catch-all should not be treated as route that errors during build.
731732
// They should be rendered properly when imported in page route.

test/unit/find-page-file.test.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,22 @@ describe('findPageFile', () => {
4646
})
4747

4848
describe('isLayoutsLeafPage', () => {
49+
const pageExtensions = ['tsx', 'ts', 'jsx', 'js']
4950
it('should determine either server or client component page file as leaf node page', () => {
50-
expect(isLayoutsLeafPage('page.js')).toBe(true)
51-
expect(isLayoutsLeafPage('./page.server.js')).toBe(true)
52-
expect(isLayoutsLeafPage('./page.server.jsx')).toBe(true)
53-
expect(isLayoutsLeafPage('./page.client.ts')).toBe(true)
54-
expect(isLayoutsLeafPage('./page.client.tsx')).toBe(true)
51+
expect(isLayoutsLeafPage('page.js', pageExtensions)).toBe(true)
52+
expect(isLayoutsLeafPage('./page.js', pageExtensions)).toBe(true)
53+
expect(isLayoutsLeafPage('./page.jsx', pageExtensions)).toBe(true)
54+
expect(isLayoutsLeafPage('/page.ts', pageExtensions)).toBe(true)
55+
expect(isLayoutsLeafPage('/path/page.tsx', pageExtensions)).toBe(true)
5556
})
5657

5758
it('should determine other files under layout routes as non leaf node', () => {
58-
expect(isLayoutsLeafPage('./page.component.jsx')).toBe(false)
59-
expect(isLayoutsLeafPage('layout.js')).toBe(false)
59+
expect(isLayoutsLeafPage('./not-a-page.js', pageExtensions)).toBe(false)
60+
expect(isLayoutsLeafPage('not-a-page.js', pageExtensions)).toBe(false)
61+
expect(isLayoutsLeafPage('./page.component.jsx', pageExtensions)).toBe(
62+
false
63+
)
64+
expect(isLayoutsLeafPage('layout.js', pageExtensions)).toBe(false)
65+
expect(isLayoutsLeafPage('page', pageExtensions)).toBe(false)
6066
})
6167
})

0 commit comments

Comments
 (0)