From 1c5983fe95b79cc9ea1e52d19e69adf7827eda5a Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Fri, 10 Feb 2023 14:01:00 +0100 Subject: [PATCH] Prefix basePath in navigate and prefix methods in app router (#45771) Closes #41824. ## Bug - [ ] Related issues linked using `fixes #number` - [x] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/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` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) 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`](https://github.com/vercel/next.js/blob/canary/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) --- .../next/src/client/components/app-router.tsx | 11 ++++--- .../app-dir/app-basepath/app/another/page.js | 3 ++ test/e2e/app-dir/app-basepath/app/layout.js | 7 ++++ test/e2e/app-dir/app-basepath/app/page.js | 10 ++++++ test/e2e/app-dir/app-basepath/index.test.ts | 32 +++++++++++++++++++ test/e2e/app-dir/app-basepath/next.config.js | 6 ++++ 6 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 test/e2e/app-dir/app-basepath/app/another/page.js create mode 100644 test/e2e/app-dir/app-basepath/app/layout.js create mode 100644 test/e2e/app-dir/app-basepath/app/page.js create mode 100644 test/e2e/app-dir/app-basepath/index.test.ts create mode 100644 test/e2e/app-dir/app-basepath/next.config.js diff --git a/packages/next/src/client/components/app-router.tsx b/packages/next/src/client/components/app-router.tsx index 6c14bb386d26..547b0797b2dc 100644 --- a/packages/next/src/client/components/app-router.tsx +++ b/packages/next/src/client/components/app-router.tsx @@ -37,6 +37,7 @@ import { } from './router-reducer/create-initial-router-state' import { fetchServerResponse } from './router-reducer/fetch-server-response' import { isBot } from '../../shared/lib/router/utils/is-bot' +import { addBasePath } from '../add-base-path' // Ensure the initialParallelRoutes are not combined because of double-rendering in the browser with Strict Mode. let initialParallelRoutes: CacheNode['parallelRoutes'] = @@ -189,7 +190,7 @@ function Router({ navigateType: 'push' | 'replace', forceOptimisticNavigation: boolean ) => { - const url = new URL(href, location.origin) + const url = new URL(addBasePath(href), location.origin) return dispatch({ type: ACTION_NAVIGATE, @@ -212,15 +213,17 @@ function Router({ back: () => window.history.back(), forward: () => window.history.forward(), prefetch: async (href) => { + const hrefWithBasePath = addBasePath(href) + // If prefetch has already been triggered, don't trigger it again. if ( - prefetched.has(href) || + prefetched.has(hrefWithBasePath) || (typeof window !== 'undefined' && isBot(window.navigator.userAgent)) ) { return } - prefetched.add(href) - const url = new URL(href, location.origin) + prefetched.add(hrefWithBasePath) + const url = new URL(hrefWithBasePath, location.origin) // External urls can't be prefetched in the same way. if (isExternalURL(url)) { return diff --git a/test/e2e/app-dir/app-basepath/app/another/page.js b/test/e2e/app-dir/app-basepath/app/another/page.js new file mode 100644 index 000000000000..9202c6325d9d --- /dev/null +++ b/test/e2e/app-dir/app-basepath/app/another/page.js @@ -0,0 +1,3 @@ +export default function Page() { + return
Page 2
+} diff --git a/test/e2e/app-dir/app-basepath/app/layout.js b/test/e2e/app-dir/app-basepath/app/layout.js new file mode 100644 index 000000000000..a3a86a5ca1e1 --- /dev/null +++ b/test/e2e/app-dir/app-basepath/app/layout.js @@ -0,0 +1,7 @@ +export default function Root({ children }) { + return ( + + {children} + + ) +} diff --git a/test/e2e/app-dir/app-basepath/app/page.js b/test/e2e/app-dir/app-basepath/app/page.js new file mode 100644 index 000000000000..852f704e6c0e --- /dev/null +++ b/test/e2e/app-dir/app-basepath/app/page.js @@ -0,0 +1,10 @@ +import Link from 'next/link' + +export default function Page() { + return ( +
+

Test Page

+ Go to page 2 +
+ ) +} diff --git a/test/e2e/app-dir/app-basepath/index.test.ts b/test/e2e/app-dir/app-basepath/index.test.ts new file mode 100644 index 000000000000..1cd3880f748d --- /dev/null +++ b/test/e2e/app-dir/app-basepath/index.test.ts @@ -0,0 +1,32 @@ +import { createNextDescribe } from 'e2e-utils' + +createNextDescribe( + 'app dir basepath', + { + files: __dirname, + skipDeployment: true, + dependencies: { + swr: '2.0.0-rc.0', + react: 'latest', + 'react-dom': 'latest', + sass: 'latest', + }, + }, + ({ next }) => { + it('should support `basePath`', async () => { + const html = await next.render('/base') + expect(html).toContain('

Test Page

') + }) + + it('should support Link with basePath prefixed', async () => { + const browser = await next.browser('/base') + expect( + await browser + .elementByCss('a[href="/base/another"]') + .click() + .waitForElementByCss('#page-2') + .text() + ).toBe(`Page 2`) + }) + } +) diff --git a/test/e2e/app-dir/app-basepath/next.config.js b/test/e2e/app-dir/app-basepath/next.config.js new file mode 100644 index 000000000000..3a1beb075adc --- /dev/null +++ b/test/e2e/app-dir/app-basepath/next.config.js @@ -0,0 +1,6 @@ +module.exports = { + basePath: '/base', + experimental: { + appDir: true, + }, +}