From 6b478d42a9826be763f78f5e39428db0a9926a11 Mon Sep 17 00:00:00 2001 From: Zack Tanner Date: Wed, 21 Feb 2024 17:54:15 -0800 Subject: [PATCH] Remove default fallback behavior when route group is missing a default --- .../build/webpack/loaders/next-app-loader.ts | 20 +-- .../(level3)/@slot/(...)photos/[id]/page.tsx | 5 - .../(level2)/(level3)/@slot/default.tsx | 3 - .../app/(level1)/(level2)/(level3)/layout.tsx | 11 -- .../(level2)/(level3)/photos/[id]/page.tsx | 9 -- .../interception-route-groups/app/layout.tsx | 9 -- .../@intercepted/(.)photos/[id]/page.tsx | 5 - .../(level2)/@intercepted/default.tsx | 3 - .../app/nested/(level1)/(level2)/layout.tsx | 11 -- .../(level1)/(level2)/photos/[id]/page.tsx | 10 -- .../app/nested/default.tsx | 3 - .../app/nested/page.tsx | 10 -- .../interception-route-groups/app/page.tsx | 12 -- .../interception-route-groups.test.ts | 138 ------------------ test/turbopack-tests-manifest.json | 12 -- 15 files changed, 5 insertions(+), 256 deletions(-) delete mode 100644 test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/@slot/(...)photos/[id]/page.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/@slot/default.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/layout.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/photos/[id]/page.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/layout.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/@intercepted/(.)photos/[id]/page.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/@intercepted/default.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/layout.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/photos/[id]/page.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/nested/default.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/nested/page.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/app/page.tsx delete mode 100644 test/e2e/app-dir/interception-route-groups/interception-route-groups.test.ts diff --git a/packages/next/src/build/webpack/loaders/next-app-loader.ts b/packages/next/src/build/webpack/loaders/next-app-loader.ts index 7fa1a623c18100..b692228aa476dc 100644 --- a/packages/next/src/build/webpack/loaders/next-app-loader.ts +++ b/packages/next/src/build/webpack/loaders/next-app-loader.ts @@ -450,22 +450,12 @@ async function createTreeCodeFromPath( adjacentParallelSegment === 'children' ? '' : `/${adjacentParallelSegment}` - let defaultPath = await resolver( - `${appDirPrefix}${segmentPath}${actualSegment}/default` - ) - if (!defaultPath) { - // no default was found at this segment. Check if the normalized segment resolves a default - // for example: /(level1)/(level2)/default doesn't exist, but /default does - const normalizedDefault = await resolver( - `${appDirPrefix}${normalizeAppPath( - segmentPath - )}/${actualSegment}/default` - ) - - // if a default is found, use that. Otherwise use the fallback, which will trigger a `notFound()` - defaultPath = normalizedDefault ?? PARALLEL_ROUTE_DEFAULT_PATH - } + // if a default is found, use that. Otherwise use the fallback, which will trigger a `notFound()` + const defaultPath = + (await resolver( + `${appDirPrefix}${segmentPath}${actualSegment}/default` + )) ?? PARALLEL_ROUTE_DEFAULT_PATH nestedCollectedAsyncImports.push(defaultPath) props[normalizeParallelKey(adjacentParallelSegment)] = `[ diff --git a/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/@slot/(...)photos/[id]/page.tsx b/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/@slot/(...)photos/[id]/page.tsx deleted file mode 100644 index dbb0e12147f4b3..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/@slot/(...)photos/[id]/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export default function Page({ params }: { params: { id: string } }) { - return
Intercepted Photo Page {params.id}
-} diff --git a/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/@slot/default.tsx b/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/@slot/default.tsx deleted file mode 100644 index a51a27b2c700df..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/@slot/default.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Default() { - return
@slot default
-} diff --git a/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/layout.tsx b/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/layout.tsx deleted file mode 100644 index 48e24fca9c8eb9..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/layout.tsx +++ /dev/null @@ -1,11 +0,0 @@ -export default function Layout(props: { - children: React.ReactNode - slot: React.ReactNode -}) { - return ( -
-
{props.children}
-
{props.slot}
-
- ) -} diff --git a/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/photos/[id]/page.tsx b/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/photos/[id]/page.tsx deleted file mode 100644 index 8b7f2063df4210..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/photos/[id]/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import Link from 'next/link' - -export default function Page({ params }: { params: { id: string } }) { - return ( -
- Photo Page (non-intercepted) {params.id} Back Home -
- ) -} diff --git a/test/e2e/app-dir/interception-route-groups/app/layout.tsx b/test/e2e/app-dir/interception-route-groups/app/layout.tsx deleted file mode 100644 index 3784e3e71e6f6d..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/layout.tsx +++ /dev/null @@ -1,9 +0,0 @@ -export default function Layout(props: { children: React.ReactNode }) { - return ( - - -
{props.children}
- - - ) -} diff --git a/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/@intercepted/(.)photos/[id]/page.tsx b/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/@intercepted/(.)photos/[id]/page.tsx deleted file mode 100644 index dbb0e12147f4b3..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/@intercepted/(.)photos/[id]/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export default function Page({ params }: { params: { id: string } }) { - return
Intercepted Photo Page {params.id}
-} diff --git a/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/@intercepted/default.tsx b/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/@intercepted/default.tsx deleted file mode 100644 index 3c0f010f6d7ae6..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/@intercepted/default.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Page() { - return
@intercepted default
-} diff --git a/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/layout.tsx b/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/layout.tsx deleted file mode 100644 index 3fd2b98c1e124f..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/layout.tsx +++ /dev/null @@ -1,11 +0,0 @@ -export default function Layout(props: { - children: React.ReactNode - intercepted: React.ReactNode -}) { - return ( -
-
{props.children}
-
{props.intercepted}
-
- ) -} diff --git a/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/photos/[id]/page.tsx b/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/photos/[id]/page.tsx deleted file mode 100644 index 463b480b0955d3..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/photos/[id]/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import Link from 'next/link' - -export default function Page({ params }: { params: { id: string } }) { - return ( -
- Photo Page (non-intercepted) {params.id}{' '} - Back to /nested -
- ) -} diff --git a/test/e2e/app-dir/interception-route-groups/app/nested/default.tsx b/test/e2e/app-dir/interception-route-groups/app/nested/default.tsx deleted file mode 100644 index fd94c8f3070544..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/nested/default.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Default() { - return
Default Children (nested)
-} diff --git a/test/e2e/app-dir/interception-route-groups/app/nested/page.tsx b/test/e2e/app-dir/interception-route-groups/app/nested/page.tsx deleted file mode 100644 index b5499fd55ed546..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/nested/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import Link from 'next/link' - -export default function Page() { - return ( -
- Photo 1{' '} - Photo 2 -
- ) -} diff --git a/test/e2e/app-dir/interception-route-groups/app/page.tsx b/test/e2e/app-dir/interception-route-groups/app/page.tsx deleted file mode 100644 index 4417311cca46ea..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/app/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import Link from 'next/link' - -export default function Page() { - return ( -
- Photo 1{' '} - Photo 2 -
- To /nested -
- ) -} diff --git a/test/e2e/app-dir/interception-route-groups/interception-route-groups.test.ts b/test/e2e/app-dir/interception-route-groups/interception-route-groups.test.ts deleted file mode 100644 index 548af8faa8f682..00000000000000 --- a/test/e2e/app-dir/interception-route-groups/interception-route-groups.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { createNextDescribe } from 'e2e-utils' -import { check } from 'next-test-utils' -import { FileRef } from 'e2e-utils' -import path from 'path' - -createNextDescribe( - 'interception route groups (with default)', - { - files: { - app: new FileRef(path.join(__dirname, 'app')), - 'app/default.tsx': ` - export default function Default() { - return
Default Children (Root)
- } - `, - }, - }, - ({ next }) => { - it("should render the root default when a route group doesn't have a default", async () => { - const browser = await next.browser('/') - - await browser.elementByCss('[href="/photos/1"]').click() - // this route was intercepted, so we should see the slot contain the page content - await check( - () => browser.elementById('slot').text(), - /Intercepted Photo Page 1/ - ) - - // and the children slot should be whatever is specified by default (in this case, default is defined at the root of the app) - await check( - () => browser.elementById('children').text(), - /Default Children \(Root\)/ - ) - - await browser.refresh() - - // once we reload, the route is no longer intercepted. The slot will fallback to the default - // and the children slot will be whatever is specified by the corresponding page component - await check(() => browser.elementById('slot').text(), /@slot default/) - await check( - () => browser.elementById('children').text(), - /Photo Page \(non-intercepted\) 1/ - ) - - await browser.elementByCss('[href="/"]').click() - - // perform the same checks as above, but with the other page - await browser.elementByCss('[href="/photos/2"]').click() - await check( - () => browser.elementById('slot').text(), - /Intercepted Photo Page 2/ - ) - await check( - () => browser.elementById('children').text(), - /Default Children \(Root\)/ - ) - - await browser.refresh() - - await check(() => browser.elementById('slot').text(), /@slot default/) - await check( - () => browser.elementById('children').text(), - /Photo Page \(non-intercepted\) 2/ - ) - }) - - it('should work when nested a level deeper', async () => { - const browser = await next.browser('/nested') - await browser.elementByCss('[href="/nested/photos/1"]').click() - - // this route was intercepted, so we should see the slot contain the page content - await check( - () => browser.elementById('slot').text(), - /Intercepted Photo Page 1/ - ) - - // and the children slot should be whatever is specified by default (in this case, default is defined at `/nested/default`) - await check( - () => browser.elementById('children').text(), - /Default Children \(nested\)/ - ) - - await browser.refresh() - - // once we reload, the route is no longer intercepted. The slot will fallback to the default - // and the children slot will be whatever is specified by the corresponding page component - await check( - () => browser.elementById('slot').text(), - /@intercepted default/ - ) - await check( - () => browser.elementById('children').text(), - /Photo Page \(non-intercepted\) 1/ - ) - - await browser.elementByCss('[href="/nested"]').click() - - // perform the same checks as above, but with the other page - await browser.elementByCss('[href="/nested/photos/2"]').click() - await check( - () => browser.elementById('slot').text(), - /Intercepted Photo Page 2/ - ) - await check( - () => browser.elementById('children').text(), - /Default Children \(nested\)/ - ) - - await browser.refresh() - - await check( - () => browser.elementById('slot').text(), - /@intercepted default/ - ) - await check( - () => browser.elementById('children').text(), - /Photo Page \(non-intercepted\) 2/ - ) - }) - } -) - -createNextDescribe( - 'interception route groups (no default)', - { - files: { - app: new FileRef(path.join(__dirname, 'app')), - }, - }, - ({ next }) => { - it('should use the default fallback (a 404) if there is no custom default page', async () => { - const browser = await next.browser('/') - - await browser.elementByCss('[href="/photos/1"]').click() - await check(() => browser.elementByCss('body').text(), /404/) - }) - } -) diff --git a/test/turbopack-tests-manifest.json b/test/turbopack-tests-manifest.json index e07b04d83931ca..3c68653e11a157 100644 --- a/test/turbopack-tests-manifest.json +++ b/test/turbopack-tests-manifest.json @@ -3563,18 +3563,6 @@ "flakey": [], "runtimeError": false }, - "test/e2e/app-dir/interception-route-groups/interception-route-groups.test.ts": { - "passed": [ - "interception route groups (no default) should use the default fallback (a 404) if there is no custom default page" - ], - "failed": [ - "interception route groups (with default) should render the root default when a route group doesn't have a default", - "interception route groups (with default) should work when nested a level deeper" - ], - "pending": [], - "flakey": [], - "runtimeError": false - }, "test/e2e/app-dir/interception-route-prefetch-cache/interception-route-prefetch-cache.test.ts": { "passed": [ "interception-route-prefetch-cache runtime = edge should render the correct interception when two distinct layouts share the same path structure",