Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion e2e/react-start/basic/src/routes/users.$userId.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
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'
import { NotFound } from '~/components/NotFound'

export const Route = createFileRoute('/users/$userId')({
loader: async ({ params: { userId } }) => {
const router = await getRouterInstance()
return await axios
.get<User>('/api/users/' + userId)
.get<User>('/api/users/' + userId, { baseURL: router.options.origin })
.then((r) => r.data)
.catch(() => {
throw new Error('Failed to fetch user')
Expand Down
4 changes: 3 additions & 1 deletion e2e/react-start/basic/src/routes/users.tsx
Original file line number Diff line number Diff line change
@@ -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<Array<User>>('/api/users')
.get<Array<User>>('/api/users', { baseURL: router.options.origin })
.then((r) => r.data)
.catch(() => {
throw new Error('Failed to fetch users')
Expand Down
10 changes: 0 additions & 10 deletions e2e/react-start/basic/tests/prerendering.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.')
})
})
})
2 changes: 1 addition & 1 deletion e2e/react-start/basic/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand All @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion e2e/solid-start/basic/src/routes/users.$userId.tsx
Original file line number Diff line number Diff line change
@@ -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<User>('/api/users/' + userId)
.get<User>('/api/users/' + userId, { baseURL: router.options.origin })
.then((r) => r.data)
.catch(() => {
throw new Error('Failed to fetch user')
Expand Down
4 changes: 3 additions & 1 deletion e2e/solid-start/basic/src/routes/users.tsx
Original file line number Diff line number Diff line change
@@ -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<Array<User>>('/api/users')
.get<Array<User>>('/api/users', { baseURL: router.options.origin })
.then((r) => r.data)
.catch(() => {
throw new Error('Failed to fetch users')
Expand Down
10 changes: 0 additions & 10 deletions e2e/solid-start/basic/tests/prerendering.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.')
})
})
})
2 changes: 1 addition & 1 deletion e2e/solid-start/basic/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const prerenderConfiguration = {
'/not-found/via-loader',
'/search-params/default',
'/transition',
'/users',
].some((p) => page.path.includes(p)),
maxRedirects: 100,
}
Expand All @@ -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,
Expand Down
26 changes: 16 additions & 10 deletions packages/router-core/src/ssr/transformStreamWithRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,17 @@ type ReadablePassthrough = {
destroyed: boolean
}

function createPassthrough() {
function createPassthrough(onCancel?: () => void) {
let controller: ReadableStreamDefaultController<any>
const encoder = new TextEncoder()
const stream = new ReadableStream({
start(c) {
controller = c
},
cancel() {
res.destroyed = true
onCancel?.()
},
})

const res: ReadablePassthrough = {
Expand Down Expand Up @@ -96,7 +100,13 @@ export function transformStreamWithRouter(
timeoutMs?: number
},
) {
const finalPassThrough = createPassthrough()
let stopListeningToInjectedHtml: (() => void) | undefined = undefined
let timeoutHandle: NodeJS.Timeout

const finalPassThrough = createPassthrough(() => {
stopListeningToInjectedHtml?.()
clearTimeout(timeoutHandle)
})
const textDecoder = new TextDecoder()

let isAppRendering = true as boolean
Expand All @@ -105,7 +115,6 @@ export function transformStreamWithRouter(
let streamBarrierLifted = false as boolean
let leftover = ''
let leftoverHtml = ''
let timeoutHandle: NodeJS.Timeout

function getBufferedRouterStream() {
const html = routerStreamBuffer
Expand All @@ -130,12 +139,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<string>) {
processingCount++
Expand Down Expand Up @@ -170,7 +176,7 @@ export function transformStreamWithRouter(
console.error('Error reading routerStream:', err)
finalPassThrough.destroy(err)
})
.finally(stopListeningToInjectedHtml)
.finally(() => stopListeningToInjectedHtml?.())

// Transform the appStream
readStream(appStream, {
Expand Down
Loading
Loading