From ebee2bafa935b6474d87a45060ffeb9b7770359f Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sat, 24 Oct 2020 14:22:48 -0500 Subject: [PATCH] Ensure 404 with SSG is rendered correctly with notFound (#18205) This ensures a custom `/404` page with `getStaticProps` works correctly when leveraging the new `unstable_notFound` support in `getStaticProps` Closes: https://github.com/vercel/next.js/issues/18196 x-ref: https://github.com/vercel/next.js/pull/17755 --- packages/next/next-server/server/next-server.ts | 14 +++++++++++--- packages/next/next-server/server/render.tsx | 6 ++++++ test/integration/i18n-support/pages/404.js | 16 ++++++++++++++++ test/integration/i18n-support/test/index.test.js | 5 +++++ yarn.lock | 7 ++++--- 5 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 test/integration/i18n-support/pages/404.js diff --git a/packages/next/next-server/server/next-server.ts b/packages/next/next-server/server/next-server.ts index 8fbb705866445d0..e478f1da66bc022 100644 --- a/packages/next/next-server/server/next-server.ts +++ b/packages/next/next-server/server/next-server.ts @@ -1183,8 +1183,10 @@ export default class Server { { components, query }: FindComponentsResult, opts: RenderOptsPartial ): Promise { + const is404Page = pathname === '/404' + // we need to ensure the status code if /404 is visited directly - if (pathname === '/404') { + if (is404Page) { res.statusCode = 404 } @@ -1255,13 +1257,19 @@ export default class Server { urlPathname = stripNextDataPath(urlPathname) } - const ssgCacheKey = + let ssgCacheKey = isPreviewMode || !isSSG ? undefined // Preview mode bypasses the cache : `${locale ? `/${locale}` : ''}${resolvedUrlPathname}${ query.amp ? '.amp' : '' }` + if (is404Page && isSSG) { + ssgCacheKey = `${locale ? `/${locale}` : ''}${pathname}${ + query.amp ? '.amp' : '' + }` + } + // Complete the response with cached data if its present const cachedData = ssgCacheKey ? await this.incrementalCache.get(ssgCacheKey) @@ -1307,7 +1315,7 @@ export default class Server { // If we're here, that means data is missing or it's stale. const maybeCoalesceInvoke = ssgCacheKey - ? (fn: any) => withCoalescedInvoke(fn).bind(null, ssgCacheKey, []) + ? (fn: any) => withCoalescedInvoke(fn).bind(null, ssgCacheKey!, []) : (fn: any) => async () => { const value = await fn() return { isOrigin: true, value } diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx index ff23d179b3135b2..1cd05e6b21823bf 100644 --- a/packages/next/next-server/server/render.tsx +++ b/packages/next/next-server/server/render.tsx @@ -637,6 +637,12 @@ export async function renderToHTML( } if (data.unstable_notFound) { + if (pathname === '/404') { + throw new Error( + `The /404 page can not return unstable_notFound in "getStaticProps", please remove it to continue!` + ) + } + ;(renderOpts as any).ssgNotFound = true ;(renderOpts as any).revalidate = false return null diff --git a/test/integration/i18n-support/pages/404.js b/test/integration/i18n-support/pages/404.js new file mode 100644 index 000000000000000..9dfbdaef04ee119 --- /dev/null +++ b/test/integration/i18n-support/pages/404.js @@ -0,0 +1,16 @@ +export default function NotFound(props) { + return ( + <> +

This page could not be found | 404

+

{JSON.stringify(props)}

+ + ) +} + +export const getStaticProps = () => { + return { + props: { + is404: true, + }, + } +} diff --git a/test/integration/i18n-support/test/index.test.js b/test/integration/i18n-support/test/index.test.js index a62672b55ef4391..1074df759376555 100644 --- a/test/integration/i18n-support/test/index.test.js +++ b/test/integration/i18n-support/test/index.test.js @@ -79,6 +79,11 @@ function runTests(isDev) { initialRevalidateSeconds: false, srcRoute: null, }, + '/404': { + dataRoute: `/_next/data/${buildId}/404.json`, + initialRevalidateSeconds: false, + srcRoute: null, + }, '/en-US/gsp/fallback/first': { dataRoute: `/_next/data/${buildId}/en-US/gsp/fallback/first.json`, initialRevalidateSeconds: false, diff --git a/yarn.lock b/yarn.lock index 829b25a7f784843..3e22fcac28b1971 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15826,9 +15826,10 @@ styled-jsx-plugin-postcss@2.0.1: postcss "^7.0.2" postcss-load-plugins "^2.3.0" -styled-jsx@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-3.3.0.tgz#32335c1a3ecfc923ba4f9c056eeb3d4699006b09" +styled-jsx@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-3.3.1.tgz#d79f306c42c99cefbe8e76f35dad8100dc5c9ecc" + integrity sha512-RhW71t3k95E3g7Zq3lEBk+kmf+p4ZME7c5tfsYf9M5mq6CgIvFXkbvhawL2gWriXLRlMyKAYACE89Qa2JnTqUw== dependencies: "@babel/types" "7.8.3" babel-plugin-syntax-jsx "6.18.0"