From d7735af93370bdf70ed22c66614ce578d62d94d9 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Tue, 18 Nov 2025 23:32:08 +0100 Subject: [PATCH 1/7] fix: memory leaks --- .../src/createStartHandler.ts | 422 +++++++++--------- 1 file changed, 200 insertions(+), 222 deletions(-) diff --git a/packages/start-server-core/src/createStartHandler.ts b/packages/start-server-core/src/createStartHandler.ts index 08ce599e40..20392dcd98 100644 --- a/packages/start-server-core/src/createStartHandler.ts +++ b/packages/start-server-core/src/createStartHandler.ts @@ -76,208 +76,221 @@ export function createStartHandler( } } - const originalFetch = globalThis.fetch - const startRequestResolver: RequestHandler = async ( request, requestOpts, ) => { - const origin = getOrigin(request) - - // Patching fetch function to use our request resolver - // if the input starts with `/` which is a common pattern for - // client-side routing. - // When we encounter similar requests, we can assume that the - // user wants to use the same origin as the current request. - globalThis.fetch = async function (input, init) { - function resolve(url: URL, requestOptions: RequestInit | undefined) { - const fetchRequest = new Request(url, requestOptions) - return startRequestResolver(fetchRequest, requestOpts) - } - - if (typeof input === 'string' && input.startsWith('/')) { - // e.g: fetch('/api/data') - const url = new URL(input, origin) - return resolve(url, init) - } else if ( - typeof input === 'object' && - 'url' in input && - typeof input.url === 'string' && - input.url.startsWith('/') - ) { - // e.g: fetch(new Request('/api/data')) - const url = new URL(input.url, origin) - return resolve(url, init) - } - - // If not, it should just use the original fetch - return originalFetch(input, init) - } as typeof fetch - - const url = new URL(request.url) - const href = url.href.replace(url.origin, '') - - let router: AnyRouter | null = null - const getRouter = async () => { - if (router) return router - router = await (await getEntries()).routerEntry.getRouter() - - // Update the client-side router with the history - const isPrerendering = process.env.TSS_PRERENDERING === 'true' - // env var is set during dev is SPA mode is enabled - let isShell = process.env.TSS_SHELL === 'true' - if (isPrerendering && !isShell) { - // only read the shell header if we are prerendering - // to avoid runtime behavior changes by injecting this header - // the header is set by the prerender plugin - isShell = request.headers.get(HEADERS.TSS_SHELL) === 'true' - } - - // Create a history for the client-side router - const history = createMemoryHistory({ - initialEntries: [href], - }) - - router.update({ - history, - isShell, - isPrerendering, - origin: router.options.origin ?? origin, - ...{ - defaultSsr: startOptions.defaultSsr, - serializationAdapters: [ - ...(startOptions.serializationAdapters || []), - ...(router.options.serializationAdapters || []), - ], - }, - basepath: ROUTER_BASEPATH, - }) - return router - } + let router: AnyRouter | null = null as AnyRouter | null + try { + const origin = getOrigin(request) + + const url = new URL(request.url) + const href = url.href.replace(url.origin, '') + + const getRouter = async () => { + if (router) return router + router = await (await getEntries()).routerEntry.getRouter() + + // Update the client-side router with the history + const isPrerendering = process.env.TSS_PRERENDERING === 'true' + // env var is set during dev is SPA mode is enabled + let isShell = process.env.TSS_SHELL === 'true' + if (isPrerendering && !isShell) { + // only read the shell header if we are prerendering + // to avoid runtime behavior changes by injecting this header + // the header is set by the prerender plugin + isShell = request.headers.get(HEADERS.TSS_SHELL) === 'true' + } - const startOptions: AnyStartInstanceOptions = - (await (await getEntries()).startEntry.startInstance?.getOptions()) || - ({} as AnyStartInstanceOptions) - startOptions.serializationAdapters = - startOptions.serializationAdapters || [] - // insert start specific default serialization adapters - startOptions.serializationAdapters.push(ServerFunctionSerializationAdapter) - - const requestHandlerMiddleware = handlerToMiddleware( - async ({ context }) => { - const response = await runWithStartContext( - { - getRouter, - startOptions, - contextAfterGlobalMiddlewares: context, - request, + // Create a history for the client-side router + const history = createMemoryHistory({ + initialEntries: [href], + }) + + router.update({ + history, + isShell, + isPrerendering, + origin: router.options.origin ?? origin, + ...{ + defaultSsr: startOptions.defaultSsr, + serializationAdapters: [ + ...(startOptions.serializationAdapters || []), + ...(router.options.serializationAdapters || []), + ], }, - async () => { - try { - // First, let's attempt to handle server functions - if (href.startsWith(process.env.TSS_SERVER_FN_BASE)) { - return await handleServerAction({ - request, - context: requestOpts?.context, - }) - } - - const executeRouter = async ({ - serverContext, - }: { - serverContext: any - }) => { - const requestAcceptHeader = - request.headers.get('Accept') || '*/*' - const splitRequestAcceptHeader = requestAcceptHeader.split(',') - - const supportedMimeTypes = ['*/*', 'text/html'] - const isRouterAcceptSupported = supportedMimeTypes.some( - (mimeType) => - splitRequestAcceptHeader.some((acceptedMimeType) => - acceptedMimeType.trim().startsWith(mimeType), - ), - ) - - if (!isRouterAcceptSupported) { - return json( - { - error: 'Only HTML requests are supported here', - }, - { - status: 500, - }, - ) - } + basepath: ROUTER_BASEPATH, + }) + return router + } - // if the startRoutesManifest is not loaded yet, load it once - if (startRoutesManifest === null) { - startRoutesManifest = await getStartManifest() + const startOptions: AnyStartInstanceOptions = + (await (await getEntries()).startEntry.startInstance?.getOptions()) || + ({} as AnyStartInstanceOptions) + startOptions.serializationAdapters = + startOptions.serializationAdapters || [] + // insert start specific default serialization adapters + startOptions.serializationAdapters.push( + ServerFunctionSerializationAdapter, + ) + + const requestHandlerMiddleware = handlerToMiddleware( + async ({ context }) => { + const response = await runWithStartContext( + { + getRouter, + startOptions, + contextAfterGlobalMiddlewares: context, + request, + }, + async () => { + try { + // First, let's attempt to handle server functions + if (href.startsWith(process.env.TSS_SERVER_FN_BASE)) { + return await handleServerAction({ + request, + context: requestOpts?.context, + }) } - const router = await getRouter() - attachRouterServerSsrUtils({ - router, - manifest: startRoutesManifest, - }) - router.update({ additionalContext: { serverContext } }) - await router.load() + const executeRouter = async ({ + serverContext, + }: { + serverContext: any + }) => { + const requestAcceptHeader = + request.headers.get('Accept') || '*/*' + const splitRequestAcceptHeader = + requestAcceptHeader.split(',') + + const supportedMimeTypes = ['*/*', 'text/html'] + const isRouterAcceptSupported = supportedMimeTypes.some( + (mimeType) => + splitRequestAcceptHeader.some((acceptedMimeType) => + acceptedMimeType.trim().startsWith(mimeType), + ), + ) - // If there was a redirect, skip rendering the page at all - if (router.state.redirect) { - return router.state.redirect + if (!isRouterAcceptSupported) { + return json( + { + error: 'Only HTML requests are supported here', + }, + { + status: 500, + }, + ) + } + + // if the startRoutesManifest is not loaded yet, load it once + if (startRoutesManifest === null) { + startRoutesManifest = await getStartManifest() + } + const router = await getRouter() + attachRouterServerSsrUtils({ + router, + manifest: startRoutesManifest, + }) + + router.update({ additionalContext: { serverContext } }) + await router.load() + + // If there was a redirect, skip rendering the page at all + if (router.state.redirect) { + return router.state.redirect + } + + await router.serverSsr!.dehydrate() + + const responseHeaders = getStartResponseHeaders({ router }) + const response = await cb({ + request, + router, + responseHeaders, + }) + + return response } - await router.serverSsr!.dehydrate() - - const responseHeaders = getStartResponseHeaders({ router }) - const response = await cb({ + const response = await handleServerRoutes({ + getRouter, request, - router, - responseHeaders, + executeRouter, + context, }) return response - } + } catch (err) { + if (err instanceof Response) { + return err + } - const response = await handleServerRoutes({ - getRouter, - request, - executeRouter, - context, - }) - - return response - } catch (err) { - if (err instanceof Response) { - return err + throw err } + }, + ) + return response + }, + ) + + const flattenedMiddlewares = startOptions.requestMiddleware + ? flattenMiddlewares(startOptions.requestMiddleware) + : [] + const middlewares = flattenedMiddlewares.map((d) => d.options.server) + const ctx = await executeMiddleware( + [...middlewares, requestHandlerMiddleware], + { + request, + + context: requestOpts?.context || {}, + }, + ) + + const response: Response = ctx.response + + if (isRedirect(response)) { + if (isResolvedRedirect(response)) { + if (request.headers.get('x-tsr-redirect') === 'manual') { + return json( + { + ...response.options, + isSerializedRedirect: true, + }, + { + headers: response.headers, + }, + ) + } + return response + } + if ( + response.options.to && + typeof response.options.to === 'string' && + !response.options.to.startsWith('/') + ) { + throw new Error( + `Server side redirects must use absolute paths via the 'href' or 'to' options. The redirect() method's "to" property accepts an internal path only. Use the "href" property to provide an external URL. Received: ${JSON.stringify(response.options)}`, + ) + } - throw err - } - }, - ) - return response - }, - ) - - const flattenedMiddlewares = startOptions.requestMiddleware - ? flattenMiddlewares(startOptions.requestMiddleware) - : [] - const middlewares = flattenedMiddlewares.map((d) => d.options.server) - const ctx = await executeMiddleware( - [...middlewares, requestHandlerMiddleware], - { - request, - - context: requestOpts?.context || {}, - }, - ) + if ( + ['params', 'search', 'hash'].some( + (d) => typeof (response.options as any)[d] === 'function', + ) + ) { + throw new Error( + `Server side redirects must use static search, params, and hash values and do not support functional values. Received functional values for: ${Object.keys( + response.options, + ) + .filter((d) => typeof (response.options as any)[d] === 'function') + .map((d) => `"${d}"`) + .join(', ')}`, + ) + } - const response: Response = ctx.response + const router = await getRouter() + const redirect = router.resolveRedirect(response) - if (isRedirect(response)) { - if (isResolvedRedirect(response)) { if (request.headers.get('x-tsr-redirect') === 'manual') { return json( { @@ -289,52 +302,17 @@ export function createStartHandler( }, ) } - return response - } - if ( - response.options.to && - typeof response.options.to === 'string' && - !response.options.to.startsWith('/') - ) { - throw new Error( - `Server side redirects must use absolute paths via the 'href' or 'to' options. The redirect() method's "to" property accepts an internal path only. Use the "href" property to provide an external URL. Received: ${JSON.stringify(response.options)}`, - ) - } - if ( - ['params', 'search', 'hash'].some( - (d) => typeof (response.options as any)[d] === 'function', - ) - ) { - throw new Error( - `Server side redirects must use static search, params, and hash values and do not support functional values. Received functional values for: ${Object.keys( - response.options, - ) - .filter((d) => typeof (response.options as any)[d] === 'function') - .map((d) => `"${d}"`) - .join(', ')}`, - ) + return redirect } - const router = await getRouter() - const redirect = router.resolveRedirect(response) - - if (request.headers.get('x-tsr-redirect') === 'manual') { - return json( - { - ...response.options, - isSerializedRedirect: true, - }, - { - headers: response.headers, - }, - ) + return response + } finally { + if (router) { + router.serverSsr = undefined + router = null } - - return redirect } - - return response } return requestHandler(startRequestResolver) From a6494bd41bc14441fb23e0935596c9fd45ad1b89 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Tue, 18 Nov 2025 23:41:18 +0100 Subject: [PATCH 2/7] more fixes --- .../src/createStartHandler.ts | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/start-server-core/src/createStartHandler.ts b/packages/start-server-core/src/createStartHandler.ts index 20392dcd98..6534514882 100644 --- a/packages/start-server-core/src/createStartHandler.ts +++ b/packages/start-server-core/src/createStartHandler.ts @@ -87,6 +87,20 @@ export function createStartHandler( const url = new URL(request.url) const href = url.href.replace(url.origin, '') + const startOptions: AnyStartInstanceOptions = + (await (await getEntries()).startEntry.startInstance?.getOptions()) || + ({} as AnyStartInstanceOptions) + + const serializationAdapters = [ + ...(startOptions.serializationAdapters || []), + ServerFunctionSerializationAdapter, + ] + + const requestStartOptions = { + ...startOptions, + serializationAdapters, + } + const getRouter = async () => { if (router) return router router = await (await getEntries()).routerEntry.getRouter() @@ -113,9 +127,9 @@ export function createStartHandler( isPrerendering, origin: router.options.origin ?? origin, ...{ - defaultSsr: startOptions.defaultSsr, + defaultSsr: requestStartOptions.defaultSsr, serializationAdapters: [ - ...(startOptions.serializationAdapters || []), + ...requestStartOptions.serializationAdapters, ...(router.options.serializationAdapters || []), ], }, @@ -124,22 +138,12 @@ export function createStartHandler( return router } - const startOptions: AnyStartInstanceOptions = - (await (await getEntries()).startEntry.startInstance?.getOptions()) || - ({} as AnyStartInstanceOptions) - startOptions.serializationAdapters = - startOptions.serializationAdapters || [] - // insert start specific default serialization adapters - startOptions.serializationAdapters.push( - ServerFunctionSerializationAdapter, - ) - const requestHandlerMiddleware = handlerToMiddleware( async ({ context }) => { const response = await runWithStartContext( { getRouter, - startOptions, + startOptions: requestStartOptions, contextAfterGlobalMiddlewares: context, request, }, @@ -309,7 +313,6 @@ export function createStartHandler( return response } finally { if (router) { - router.serverSsr = undefined router = null } } From 7b2bbfa205fd610fa08ed1705711d2fd08582f2b Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Tue, 18 Nov 2025 23:49:27 +0100 Subject: [PATCH 3/7] more fixes --- .../src/ssr/transformStreamWithRouter.ts | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/router-core/src/ssr/transformStreamWithRouter.ts b/packages/router-core/src/ssr/transformStreamWithRouter.ts index dec03fe80b..e231abee0d 100644 --- a/packages/router-core/src/ssr/transformStreamWithRouter.ts +++ b/packages/router-core/src/ssr/transformStreamWithRouter.ts @@ -35,13 +35,17 @@ type ReadablePassthrough = { destroyed: boolean } -function createPassthrough() { +function createPassthrough(onCancel?: () => void) { let controller: ReadableStreamDefaultController const encoder = new TextEncoder() const stream = new ReadableStream({ start(c) { controller = c }, + cancel() { + res.destroyed = true + onCancel?.() + }, }) const res: ReadablePassthrough = { @@ -96,7 +100,11 @@ export function transformStreamWithRouter( timeoutMs?: number }, ) { - const finalPassThrough = createPassthrough() + let stopListeningToInjectedHtml: (() => void) | undefined = undefined + + const finalPassThrough = createPassthrough(() => { + stopListeningToInjectedHtml?.() + }) const textDecoder = new TextDecoder() let isAppRendering = true as boolean @@ -130,12 +138,9 @@ export function transformStreamWithRouter( }) // Listen for any new injected HTML - const stopListeningToInjectedHtml = router.subscribe( - 'onInjectedHtml', - (e) => { - handleInjectedHtml(e.promise) - }, - ) + stopListeningToInjectedHtml = router.subscribe('onInjectedHtml', (e) => { + handleInjectedHtml(e.promise) + }) function handleInjectedHtml(promise: Promise) { processingCount++ @@ -170,7 +175,7 @@ export function transformStreamWithRouter( console.error('Error reading routerStream:', err) finalPassThrough.destroy(err) }) - .finally(stopListeningToInjectedHtml) + .finally(() => stopListeningToInjectedHtml?.()) // Transform the appStream readStream(appStream, { From 55043474a40609a478a9ea3a3ac7b742fb0ae127 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 19 Nov 2025 00:43:53 +0100 Subject: [PATCH 4/7] clear timeout --- packages/router-core/src/ssr/transformStreamWithRouter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/router-core/src/ssr/transformStreamWithRouter.ts b/packages/router-core/src/ssr/transformStreamWithRouter.ts index e231abee0d..ee2abcab43 100644 --- a/packages/router-core/src/ssr/transformStreamWithRouter.ts +++ b/packages/router-core/src/ssr/transformStreamWithRouter.ts @@ -101,9 +101,11 @@ export function transformStreamWithRouter( }, ) { let stopListeningToInjectedHtml: (() => void) | undefined = undefined + let timeoutHandle: NodeJS.Timeout const finalPassThrough = createPassthrough(() => { stopListeningToInjectedHtml?.() + clearTimeout(timeoutHandle) }) const textDecoder = new TextDecoder() @@ -113,7 +115,6 @@ export function transformStreamWithRouter( let streamBarrierLifted = false as boolean let leftover = '' let leftoverHtml = '' - let timeoutHandle: NodeJS.Timeout function getBufferedRouterStream() { const html = routerStreamBuffer From 7cfa14ee749511ed94754661d6ad4b74d530a4fa Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 19 Nov 2025 00:44:18 +0100 Subject: [PATCH 5/7] fix tests to not rely on fetch patch serverside --- e2e/react-start/basic/src/routes/users.$userId.tsx | 4 +++- e2e/react-start/basic/src/routes/users.tsx | 4 +++- e2e/solid-start/basic/src/routes/users.$userId.tsx | 4 +++- e2e/solid-start/basic/src/routes/users.tsx | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/e2e/react-start/basic/src/routes/users.$userId.tsx b/e2e/react-start/basic/src/routes/users.$userId.tsx index e293be3731..59ddc3df87 100644 --- a/e2e/react-start/basic/src/routes/users.$userId.tsx +++ b/e2e/react-start/basic/src/routes/users.$userId.tsx @@ -1,5 +1,6 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import axios from 'redaxios' +import { getRouterInstance } from '@tanstack/react-start' import type { ErrorComponentProps } from '@tanstack/react-router' import type { User } from '~/utils/users' @@ -7,8 +8,9 @@ import { NotFound } from '~/components/NotFound' export const Route = createFileRoute('/users/$userId')({ loader: async ({ params: { userId } }) => { + const router = await getRouterInstance() return await axios - .get('/api/users/' + userId) + .get('/api/users/' + userId, { baseURL: router.options.origin }) .then((r) => r.data) .catch(() => { throw new Error('Failed to fetch user') diff --git a/e2e/react-start/basic/src/routes/users.tsx b/e2e/react-start/basic/src/routes/users.tsx index 7b08d61652..f7a5721097 100644 --- a/e2e/react-start/basic/src/routes/users.tsx +++ b/e2e/react-start/basic/src/routes/users.tsx @@ -1,12 +1,14 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' +import { getRouterInstance } from '@tanstack/react-start' import axios from 'redaxios' import type { User } from '~/utils/users' export const Route = createFileRoute('/users')({ loader: async () => { + const router = await getRouterInstance() return await axios - .get>('/api/users') + .get>('/api/users', { baseURL: router.options.origin }) .then((r) => r.data) .catch(() => { throw new Error('Failed to fetch users') diff --git a/e2e/solid-start/basic/src/routes/users.$userId.tsx b/e2e/solid-start/basic/src/routes/users.$userId.tsx index 4afb3bbe7c..ccc37e78f5 100644 --- a/e2e/solid-start/basic/src/routes/users.$userId.tsx +++ b/e2e/solid-start/basic/src/routes/users.$userId.tsx @@ -1,14 +1,16 @@ import { createFileRoute } from '@tanstack/solid-router' import axios from 'redaxios' +import { getRouterInstance } from '@tanstack/solid-start' import type { User } from '~/utils/users' import { NotFound } from '~/components/NotFound' import { UserErrorComponent } from '~/components/UserErrorComponent' export const Route = createFileRoute('/users/$userId')({ loader: async ({ params: { userId } }) => { + const router = await getRouterInstance() return await axios - .get('/api/users/' + userId) + .get('/api/users/' + userId, { baseURL: router.options.origin }) .then((r) => r.data) .catch(() => { throw new Error('Failed to fetch user') diff --git a/e2e/solid-start/basic/src/routes/users.tsx b/e2e/solid-start/basic/src/routes/users.tsx index 18a79ca664..65878a704a 100644 --- a/e2e/solid-start/basic/src/routes/users.tsx +++ b/e2e/solid-start/basic/src/routes/users.tsx @@ -1,12 +1,14 @@ import { Link, Outlet, createFileRoute } from '@tanstack/solid-router' +import { getRouterInstance } from '@tanstack/solid-start' import axios from 'redaxios' import type { User } from '~/utils/users' export const Route = createFileRoute('/users')({ loader: async () => { + const router = await getRouterInstance() return await axios - .get>('/api/users') + .get>('/api/users', { baseURL: router.options.origin }) .then((r) => r.data) .catch(() => { throw new Error('Failed to fetch users') From 00d21da47f1c92397fdb387075d24af90f7da210 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 19 Nov 2025 01:04:27 +0100 Subject: [PATCH 6/7] disable prerendering of /users --- e2e/react-start/basic/vite.config.ts | 2 +- e2e/solid-start/basic/vite.config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/react-start/basic/vite.config.ts b/e2e/react-start/basic/vite.config.ts index c34468b880..f9249150d9 100644 --- a/e2e/react-start/basic/vite.config.ts +++ b/e2e/react-start/basic/vite.config.ts @@ -21,6 +21,7 @@ const prerenderConfiguration = { '/i-do-not-exist', '/not-found/via-beforeLoad', '/not-found/via-loader', + '/users', ].some((p) => page.path.includes(p)), maxRedirects: 100, } @@ -33,7 +34,6 @@ export default defineConfig({ tsConfigPaths({ projects: ['./tsconfig.json'], }), - // @ts-ignore we want to keep one test with verboseFileRoutes off even though the option is hidden tanstackStart({ spa: isSpaMode ? spaModeConfiguration : undefined, prerender: isPrerender ? prerenderConfiguration : undefined, diff --git a/e2e/solid-start/basic/vite.config.ts b/e2e/solid-start/basic/vite.config.ts index 8d83108574..6af116d625 100644 --- a/e2e/solid-start/basic/vite.config.ts +++ b/e2e/solid-start/basic/vite.config.ts @@ -23,6 +23,7 @@ const prerenderConfiguration = { '/not-found/via-loader', '/search-params/default', '/transition', + '/users', ].some((p) => page.path.includes(p)), maxRedirects: 100, } @@ -35,7 +36,6 @@ export default defineConfig({ tsConfigPaths({ projects: ['./tsconfig.json'], }), - // @ts-ignore we want to keep one test with verboseFileRoutes off even though the option is hidden tanstackStart({ spa: isSpaMode ? spaModeConfiguration : undefined, prerender: isPrerender ? prerenderConfiguration : undefined, From 08391ddbc1bbd8536dde41f39d50c34b54a8da1d Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 19 Nov 2025 01:08:55 +0100 Subject: [PATCH 7/7] remove tests for users prerendering --- e2e/react-start/basic/tests/prerendering.spec.ts | 10 ---------- e2e/solid-start/basic/tests/prerendering.spec.ts | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/e2e/react-start/basic/tests/prerendering.spec.ts b/e2e/react-start/basic/tests/prerendering.spec.ts index 9a3ec145dc..7718fe86ef 100644 --- a/e2e/react-start/basic/tests/prerendering.spec.ts +++ b/e2e/react-start/basic/tests/prerendering.spec.ts @@ -14,7 +14,6 @@ test.describe('Prerender Static Path Discovery', () => { // These static routes should be automatically discovered and prerendered expect(existsSync(join(distDir, 'index.html'))).toBe(true) expect(existsSync(join(distDir, 'posts/index.html'))).toBe(true) - expect(existsSync(join(distDir, 'users/index.html'))).toBe(true) expect(existsSync(join(distDir, 'deferred/index.html'))).toBe(true) expect(existsSync(join(distDir, 'scripts/index.html'))).toBe(true) expect(existsSync(join(distDir, 'inline-scripts/index.html'))).toBe(true) @@ -40,14 +39,5 @@ test.describe('Prerender Static Path Discovery', () => { const html = readFileSync(join(distDir, 'posts/index.html'), 'utf-8') expect(html).toContain('Select a post.') }) - - test('should contain prerendered content in users.html', () => { - const distDir = join(process.cwd(), 'dist', 'client') - expect(existsSync(join(distDir, 'users/index.html'))).toBe(true) - - // "Select a user." should be in the prerendered HTML - const html = readFileSync(join(distDir, 'users/index.html'), 'utf-8') - expect(html).toContain('Select a user.') - }) }) }) diff --git a/e2e/solid-start/basic/tests/prerendering.spec.ts b/e2e/solid-start/basic/tests/prerendering.spec.ts index 9a3ec145dc..02e26a14c4 100644 --- a/e2e/solid-start/basic/tests/prerendering.spec.ts +++ b/e2e/solid-start/basic/tests/prerendering.spec.ts @@ -15,7 +15,6 @@ test.describe('Prerender Static Path Discovery', () => { expect(existsSync(join(distDir, 'index.html'))).toBe(true) expect(existsSync(join(distDir, 'posts/index.html'))).toBe(true) expect(existsSync(join(distDir, 'users/index.html'))).toBe(true) - expect(existsSync(join(distDir, 'deferred/index.html'))).toBe(true) expect(existsSync(join(distDir, 'scripts/index.html'))).toBe(true) expect(existsSync(join(distDir, 'inline-scripts/index.html'))).toBe(true) expect(existsSync(join(distDir, '대한민국/index.html'))).toBe(true) @@ -40,14 +39,5 @@ test.describe('Prerender Static Path Discovery', () => { const html = readFileSync(join(distDir, 'posts/index.html'), 'utf-8') expect(html).toContain('Select a post.') }) - - test('should contain prerendered content in users.html', () => { - const distDir = join(process.cwd(), 'dist', 'client') - expect(existsSync(join(distDir, 'users/index.html'))).toBe(true) - - // "Select a user." should be in the prerendered HTML - const html = readFileSync(join(distDir, 'users/index.html'), 'utf-8') - expect(html).toContain('Select a user.') - }) }) })