From 54fce53dd98d48216e5a8fff0c98a53cf3ae49dd Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 28 Mar 2023 21:54:58 +0200 Subject: [PATCH] Make sure the global not found route doesn't conflict with existing /not-found route (#47619) In #47328 we made the root level `/not-found.js` a special entry, to override the page 404 during builds. However, it's possible that the user has a valid `/not-found/page.js` route that might conflict with this special entry. This PR changes the entry to be `/_not-found` so it will never conflict with existing valid entries. --- packages/next/src/build/entries.ts | 1 + packages/next/src/build/index.ts | 6 +++--- packages/next/src/export/worker.ts | 2 +- packages/next/src/server/base-server.ts | 2 +- test/e2e/app-dir/not-found/app/not-found/page.js | 3 +++ test/e2e/app-dir/not-found/not-found.test.ts | 5 +++++ 6 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 test/e2e/app-dir/not-found/app/not-found/page.js diff --git a/packages/next/src/build/entries.ts b/packages/next/src/build/entries.ts index 04a63d03181b3..6408d415429a4 100644 --- a/packages/next/src/build/entries.ts +++ b/packages/next/src/build/entries.ts @@ -90,6 +90,7 @@ export function createPagesMapping({ let pageKey = getPageFromPath(pagePath, pageExtensions) if (isAppRoute) { pageKey = pageKey.replace(/%5F/g, '_') + pageKey = pageKey.replace(/^\/not-found$/g, '/_not-found') } if (pageKey in result) { diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index 5ec3cad7c72e1..0dcf0332c4173 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -678,7 +678,7 @@ export default async function build( const conflictingPublicFiles: string[] = [] const hasPages404 = mappedPages['/404']?.startsWith(PAGES_DIR_ALIAS) - const hasApp404 = !!mappedAppPages?.['/not-found'] + const hasApp404 = !!mappedAppPages?.['/_not-found'] const hasCustomErrorPage = mappedPages['/_error'].startsWith(PAGES_DIR_ALIAS) @@ -2493,7 +2493,7 @@ export default async function build( routes.forEach((route) => { if (isDynamicRoute(page) && route === page) return - if (route === '/not-found') return + if (route === '/_not-found') return let revalidate = exportConfig.initialPageRevalidationMap[route] @@ -2703,7 +2703,7 @@ export default async function build( distDir, 'server', 'app', - 'not-found.html' + '_not-found.html' ) const updatedRelativeDest = path .join('pages', '404.html') diff --git a/packages/next/src/export/worker.ts b/packages/next/src/export/worker.ts index 30cb30e7f76a4..c4be7436811a3 100644 --- a/packages/next/src/export/worker.ts +++ b/packages/next/src/export/worker.ts @@ -465,7 +465,7 @@ export default async function exportPage({ try { curRenderOpts.params ||= {} - const isNotFoundPage = page === '/not-found' + const isNotFoundPage = page === '/_not-found' const result = await renderToHTMLOrFlight( req as any, res as any, diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index c001efa57d3f0..b59831b54162d 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -2247,7 +2247,7 @@ export default abstract class Server { if (this.hasAppDir) { // Use the not-found entry in app directory result = await this.findPageComponents({ - pathname: '/not-found', + pathname: this.renderOpts.dev ? '/not-found' : '/_not-found', query, params: {}, isAppPath: true, diff --git a/test/e2e/app-dir/not-found/app/not-found/page.js b/test/e2e/app-dir/not-found/app/not-found/page.js new file mode 100644 index 0000000000000..948f6d898634f --- /dev/null +++ b/test/e2e/app-dir/not-found/app/not-found/page.js @@ -0,0 +1,3 @@ +export default function Page() { + return

I'm still a valid page

+} diff --git a/test/e2e/app-dir/not-found/not-found.test.ts b/test/e2e/app-dir/not-found/not-found.test.ts index b74951b408e4c..07a43f8a1ac29 100644 --- a/test/e2e/app-dir/not-found/not-found.test.ts +++ b/test/e2e/app-dir/not-found/not-found.test.ts @@ -13,6 +13,11 @@ createNextDescribe( expect(html).toContain('This Is The Not Found Page') }) + it('should allow to have a valid /not-found route', async () => { + const html = await next.render('/not-found') + expect(html).toContain("I'm still a valid page") + }) + if (!isNextDev) { it('should create the 404 mapping and copy the file to pages', async () => { const html = await next.readFile('.next/server/pages/404.html')