diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index 29c653a7eb969..2b02c651ad160 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -1020,7 +1020,9 @@ export default async function build( const appPaths = Array.from(appPageKeys) // Interception routes are modelled as beforeFiles rewrites - rewrites.beforeFiles.push(...generateInterceptionRoutesRewrites(appPaths)) + rewrites.beforeFiles.push( + ...generateInterceptionRoutesRewrites(appPaths, config.basePath) + ) const totalAppPagesCount = appPaths.length diff --git a/packages/next/src/lib/generate-interception-routes-rewrites.ts b/packages/next/src/lib/generate-interception-routes-rewrites.ts index 85fed64167498..931f2199675c2 100644 --- a/packages/next/src/lib/generate-interception-routes-rewrites.ts +++ b/packages/next/src/lib/generate-interception-routes-rewrites.ts @@ -44,7 +44,8 @@ function voidParamsBeforeInterceptionMarker(path: string): string { } export function generateInterceptionRoutesRewrites( - appPaths: string[] + appPaths: string[], + basePath = '' ): Rewrite[] { const rewrites: Rewrite[] = [] @@ -70,8 +71,8 @@ export function generateInterceptionRoutesRewrites( .slice(2, -3) rewrites.push({ - source: normalizedInterceptedRoute, - destination: normalizedAppPath, + source: `${basePath}${normalizedInterceptedRoute}`, + destination: `${basePath}${normalizedAppPath}`, has: [ { type: 'header', diff --git a/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts b/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts index 130d54fedc6a3..5060c36fafb62 100644 --- a/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts +++ b/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts @@ -2270,7 +2270,10 @@ async function startWatcher(opts: SetupOpts) { : undefined opts.fsChecker.interceptionRoutes = - generateInterceptionRoutesRewrites(Object.keys(appPaths))?.map((item) => + generateInterceptionRoutesRewrites( + Object.keys(appPaths), + opts.nextConfig.basePath + )?.map((item) => buildCustomRoute( 'before_files_rewrite', item, diff --git a/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/@slot/(.)nested/page.tsx b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/@slot/(.)nested/page.tsx new file mode 100644 index 0000000000000..2aef38ce37662 --- /dev/null +++ b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/@slot/(.)nested/page.tsx @@ -0,0 +1,3 @@ +export default function Page() { + return
Nested Page Slot
+} diff --git a/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/@slot/default.tsx b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/@slot/default.tsx new file mode 100644 index 0000000000000..86b9e9a388129 --- /dev/null +++ b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/@slot/default.tsx @@ -0,0 +1,3 @@ +export default function Default() { + return null +} diff --git a/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/default.tsx b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/default.tsx new file mode 100644 index 0000000000000..86b9e9a388129 --- /dev/null +++ b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/default.tsx @@ -0,0 +1,3 @@ +export default function Default() { + return null +} diff --git a/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/layout.tsx b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/layout.tsx new file mode 100644 index 0000000000000..484278793ba69 --- /dev/null +++ b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/layout.tsx @@ -0,0 +1,13 @@ +export default function Layout(props: { + children: React.ReactNode + slot: React.ReactNode +}) { + return ( + + +
{props.children}
+ {props.slot} + + + ) +} diff --git a/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/nested/page.tsx b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/nested/page.tsx new file mode 100644 index 0000000000000..6775bc5e10979 --- /dev/null +++ b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/nested/page.tsx @@ -0,0 +1,3 @@ +export default function Page() { + return
Nested Page Full
+} diff --git a/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/page.tsx b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/page.tsx new file mode 100644 index 0000000000000..cf956e46eefcd --- /dev/null +++ b/test/e2e/app-dir/parallel-routes-and-interception-basepath/app/page.tsx @@ -0,0 +1,13 @@ +import Link from 'next/link' + +export default function Page() { + return ( +
+
Home page
+
+ + To Nested + +
+ ) +} diff --git a/test/e2e/app-dir/parallel-routes-and-interception-basepath/next.config.js b/test/e2e/app-dir/parallel-routes-and-interception-basepath/next.config.js new file mode 100644 index 0000000000000..1a6c394735f8b --- /dev/null +++ b/test/e2e/app-dir/parallel-routes-and-interception-basepath/next.config.js @@ -0,0 +1,8 @@ +/** + * @type {import('next').NextConfig} + */ +const nextConfig = { + basePath: '/base', +} + +module.exports = nextConfig diff --git a/test/e2e/app-dir/parallel-routes-and-interception-basepath/parallel-routes-and-interception-basepath.test.ts b/test/e2e/app-dir/parallel-routes-and-interception-basepath/parallel-routes-and-interception-basepath.test.ts new file mode 100644 index 0000000000000..a019731195511 --- /dev/null +++ b/test/e2e/app-dir/parallel-routes-and-interception-basepath/parallel-routes-and-interception-basepath.test.ts @@ -0,0 +1,25 @@ +import { createNextDescribe } from 'e2e-utils' + +createNextDescribe( + 'parallel-routes-and-interception-basepath', + { + files: __dirname, + }, + ({ next }) => { + it('should show parallel intercepted slot with basepath', async () => { + const browser = await next.browser('/base') + await browser.elementByCss('#link-to-nested').click() + const homePage = await browser.elementByCss('#home-page').text() + const slot = await browser.elementByCss('#nested-page-slot').text() + expect(homePage).toBe('Home page') + expect(slot).toBe('Nested Page Slot') + }) + it('should show normal route via direct link with basepath when parallel intercepted slot exist', async () => { + const browser = await next.browser('/base/nested') + const nestedPageFull = await browser + .elementByCss('#nested-page-full') + .text() + expect(nestedPageFull).toBe('Nested Page Full') + }) + } +)