diff --git a/packages/next/src/server/app-render/use-flight-response.tsx b/packages/next/src/server/app-render/use-flight-response.tsx index d62a3ca51bb15..1cc5b67f62d00 100644 --- a/packages/next/src/server/app-render/use-flight-response.tsx +++ b/packages/next/src/server/app-render/use-flight-response.tsx @@ -3,7 +3,8 @@ import type { FlightResponseRef } from './flight-response-ref' import { readableStreamTee } from '../stream-utils/node-web-streams-helper' import { encodeText, decodeText } from '../stream-utils/encode-decode' import { htmlEscapeJsonString } from '../htmlescape' -import { isEdgeRuntime } from './app-render' + +const isEdgeRuntime = process.env.NEXT_RUNTIME === 'edge' /** * Render Flight stream. diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 3597728f61a20..5b444af036687 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -2431,15 +2431,16 @@ export default abstract class Server { } } const { res, query } = ctx + try { let result: null | FindComponentsResult = null const is404 = res.statusCode === 404 let using404Page = false - // use static 404 page if available and is 404 response if (is404) { - if (this.hasAppDir) { + // Rendering app routes only in render worker to make sure the require-hook is setup + if (this.hasAppDir && this.isRenderWorker) { // Use the not-found entry in app directory result = await this.findPageComponents({ pathname: this.renderOpts.dev ? '/not-found' : '/_not-found', diff --git a/packages/next/src/server/lib/render-server-standalone.ts b/packages/next/src/server/lib/render-server-standalone.ts index 3843b2b73c42e..90cc1a3de0617 100644 --- a/packages/next/src/server/lib/render-server-standalone.ts +++ b/packages/next/src/server/lib/render-server-standalone.ts @@ -5,8 +5,6 @@ import httpProxy from 'next/dist/compiled/http-proxy' import { Worker } from 'next/dist/compiled/jest-worker' import { normalizeRepeatedSlashes } from '../../shared/lib/utils' -const renderServerPath = require.resolve('./render-server') - export const createServerHandler = async ({ port, hostname, @@ -20,7 +18,7 @@ export const createServerHandler = async ({ dev?: boolean minimalMode: boolean }) => { - const routerWorker = new Worker(renderServerPath, { + const routerWorker = new Worker(require.resolve('./render-server'), { numWorkers: 1, maxRetries: 10, forkOptions: { diff --git a/packages/next/src/server/next.ts b/packages/next/src/server/next.ts index 0a6f8e29a4bbe..97023cd0349f7 100644 --- a/packages/next/src/server/next.ts +++ b/packages/next/src/server/next.ts @@ -141,10 +141,10 @@ export class NextServer { } async prepare() { - const server = await this.getServer() - if (this.standaloneMode) return + const server = await this.getServer() + // We shouldn't prepare the server in production, // because this code won't be executed when deployed if (this.options.dev) { diff --git a/test/production/standalone-mode/metadata/app/favicon.ico b/test/production/standalone-mode/basic/app/favicon.ico similarity index 100% rename from test/production/standalone-mode/metadata/app/favicon.ico rename to test/production/standalone-mode/basic/app/favicon.ico diff --git a/test/production/standalone-mode/metadata/app/icon.svg b/test/production/standalone-mode/basic/app/icon.svg similarity index 100% rename from test/production/standalone-mode/metadata/app/icon.svg rename to test/production/standalone-mode/basic/app/icon.svg diff --git a/test/production/standalone-mode/metadata/app/layout.js b/test/production/standalone-mode/basic/app/layout.js similarity index 100% rename from test/production/standalone-mode/metadata/app/layout.js rename to test/production/standalone-mode/basic/app/layout.js diff --git a/test/production/standalone-mode/basic/app/not-found.js b/test/production/standalone-mode/basic/app/not-found.js new file mode 100644 index 0000000000000..87f5e3b912042 --- /dev/null +++ b/test/production/standalone-mode/basic/app/not-found.js @@ -0,0 +1,3 @@ +export default function NotFound() { + return 'app-not-found' +} diff --git a/test/production/standalone-mode/metadata/app/page.js b/test/production/standalone-mode/basic/app/page.js similarity index 100% rename from test/production/standalone-mode/metadata/app/page.js rename to test/production/standalone-mode/basic/app/page.js diff --git a/test/production/standalone-mode/basic/index.test.ts b/test/production/standalone-mode/basic/index.test.ts new file mode 100644 index 0000000000000..f738240f7e7c8 --- /dev/null +++ b/test/production/standalone-mode/basic/index.test.ts @@ -0,0 +1,44 @@ +import { createNextDescribe } from 'e2e-utils' + +createNextDescribe( + 'standalone mode - metadata routes', + { + files: __dirname, + dependencies: { + swr: 'latest', + }, + }, + ({ next }) => { + beforeAll(async () => { + // Hide source files to make sure route.js can read files from source + // in order to hit the prerender cache + await next.renameFolder('app', 'app_hidden') + }) + + it('should handle metadata icons correctly', async () => { + const faviconRes = await next.fetch('/favicon.ico') + const iconRes = await next.fetch('/icon.svg') + expect(faviconRes.status).toBe(200) + expect(iconRes.status).toBe(200) + }) + + it('should handle correctly not-found.js', async () => { + const res = await next.fetch('/not-found/does-not-exist') + expect(res.status).toBe(404) + const html = await res.text() + expect(html).toContain('app-not-found') + }) + + it('should handle private _next unmatched route correctly', async () => { + const res = await next.fetch('/_next/does-not-exist') + expect(res.status).toBe(404) + const html = await res.text() + expect(html).toContain('app-not-found') + }) + + it('should handle pages rendering correctly', async () => { + const browser = await next.browser('/hello') + expect(await browser.elementByCss('#content').text()).toBe('hello-bar') + }) + } +) diff --git a/test/production/standalone-mode/metadata/next.config.js b/test/production/standalone-mode/basic/next.config.js similarity index 100% rename from test/production/standalone-mode/metadata/next.config.js rename to test/production/standalone-mode/basic/next.config.js diff --git a/test/production/standalone-mode/basic/pages/hello.js b/test/production/standalone-mode/basic/pages/hello.js new file mode 100644 index 0000000000000..793b8060047ca --- /dev/null +++ b/test/production/standalone-mode/basic/pages/hello.js @@ -0,0 +1,16 @@ +import useSWR, { useSWRConfig } from 'swr' + +export default function Page({ foo }) { + const { data } = useSWR('hello', (v) => v, { fallbackData: 'hello' }) + useSWRConfig() // call SWR context + + return
{`${data}-${foo}`}
+} + +export function getServerSideProps() { + return { + props: { + foo: 'bar', + }, + } +} diff --git a/test/production/standalone-mode/metadata/index.test.ts b/test/production/standalone-mode/metadata/index.test.ts deleted file mode 100644 index d8a960465fa1f..0000000000000 --- a/test/production/standalone-mode/metadata/index.test.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createNextDescribe } from 'e2e-utils' - -createNextDescribe( - 'standalone mode - metadata routes', - { - files: __dirname, - }, - ({ next }) => { - beforeAll(async () => { - // Hide source files to make sure route.js can read files from source - // in order to hit the prerender cache - await next.renameFolder('app', 'app_hidden') - }) - - it('should work', async () => { - const faviconRes = await next.fetch('/favicon.ico') - const iconRes = await next.fetch('/icon.svg') - expect(faviconRes.status).toBe(200) - expect(iconRes.status).toBe(200) - }) - } -)