@tanstack/vue-router 1.140.5 → 1.141.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/Asset.js +122 -8
- package/dist/esm/Asset.js.map +1 -1
- package/dist/esm/Body.d.ts +4 -0
- package/dist/esm/Body.js +26 -0
- package/dist/esm/Body.js.map +1 -0
- package/dist/esm/CatchBoundary.d.ts +1 -1
- package/dist/esm/CatchBoundary.js +8 -8
- package/dist/esm/CatchBoundary.js.map +1 -1
- package/dist/esm/Html.d.ts +4 -0
- package/dist/esm/Html.js +63 -0
- package/dist/esm/Html.js.map +1 -0
- package/dist/esm/Match.js +87 -49
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/Matches.js +3 -2
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/RouterProvider.js +3 -0
- package/dist/esm/RouterProvider.js.map +1 -1
- package/dist/esm/ScriptOnce.d.ts +12 -5
- package/dist/esm/ScriptOnce.js +35 -15
- package/dist/esm/ScriptOnce.js.map +1 -1
- package/dist/esm/Scripts.d.ts +2 -1
- package/dist/esm/Scripts.js +101 -35
- package/dist/esm/Scripts.js.map +1 -1
- package/dist/esm/Transitioner.d.ts +16 -0
- package/dist/esm/Transitioner.js +136 -133
- package/dist/esm/Transitioner.js.map +1 -1
- package/dist/esm/awaited.d.ts +20 -5
- package/dist/esm/awaited.js +17 -20
- package/dist/esm/awaited.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lazyRouteComponent.js +2 -2
- package/dist/esm/lazyRouteComponent.js.map +1 -1
- package/dist/esm/link.js +27 -35
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/scroll-restoration.d.ts +8 -1
- package/dist/esm/scroll-restoration.js +44 -12
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/ssr/RouterClient.d.ts +15 -0
- package/dist/esm/ssr/RouterClient.js +46 -0
- package/dist/esm/ssr/RouterClient.js.map +1 -0
- package/dist/esm/ssr/RouterServer.d.ts +15 -0
- package/dist/esm/ssr/RouterServer.js +37 -0
- package/dist/esm/ssr/RouterServer.js.map +1 -0
- package/dist/esm/ssr/client.d.ts +1 -0
- package/dist/esm/ssr/client.js +5 -0
- package/dist/esm/ssr/client.js.map +1 -0
- package/dist/esm/ssr/defaultRenderHandler.d.ts +1 -0
- package/dist/esm/ssr/defaultRenderHandler.js +15 -0
- package/dist/esm/ssr/defaultRenderHandler.js.map +1 -0
- package/dist/esm/ssr/defaultStreamHandler.d.ts +1 -0
- package/dist/esm/ssr/defaultStreamHandler.js +17 -0
- package/dist/esm/ssr/defaultStreamHandler.js.map +1 -0
- package/dist/esm/ssr/renderRouterToStream.d.ts +8 -0
- package/dist/esm/ssr/renderRouterToStream.js +70 -0
- package/dist/esm/ssr/renderRouterToStream.js.map +1 -0
- package/dist/esm/ssr/renderRouterToString.d.ts +7 -0
- package/dist/esm/ssr/renderRouterToString.js +33 -0
- package/dist/esm/ssr/renderRouterToString.js.map +1 -0
- package/dist/esm/ssr/server.d.ts +6 -0
- package/dist/esm/ssr/server.js +14 -0
- package/dist/esm/ssr/server.js.map +1 -0
- package/dist/source/Asset.jsx +119 -7
- package/dist/source/Asset.jsx.map +1 -1
- package/dist/source/Body.d.ts +4 -0
- package/dist/source/Body.jsx +15 -0
- package/dist/source/Body.jsx.map +1 -0
- package/dist/source/CatchBoundary.d.ts +1 -1
- package/dist/source/CatchBoundary.jsx +10 -23
- package/dist/source/CatchBoundary.jsx.map +1 -1
- package/dist/source/Html.d.ts +4 -0
- package/dist/source/Html.jsx +56 -0
- package/dist/source/Html.jsx.map +1 -0
- package/dist/source/Match.jsx +119 -54
- package/dist/source/Match.jsx.map +1 -1
- package/dist/source/Matches.jsx +15 -3
- package/dist/source/Matches.jsx.map +1 -1
- package/dist/source/RouterProvider.jsx +5 -0
- package/dist/source/RouterProvider.jsx.map +1 -1
- package/dist/source/ScriptOnce.d.ts +12 -5
- package/dist/source/ScriptOnce.jsx +27 -16
- package/dist/source/ScriptOnce.jsx.map +1 -1
- package/dist/source/Scripts.d.ts +2 -1
- package/dist/source/Scripts.jsx +100 -42
- package/dist/source/Scripts.jsx.map +1 -1
- package/dist/source/Transitioner.d.ts +16 -0
- package/dist/source/Transitioner.jsx +180 -160
- package/dist/source/Transitioner.jsx.map +1 -1
- package/dist/source/awaited.d.ts +20 -5
- package/dist/source/awaited.jsx +18 -25
- package/dist/source/awaited.jsx.map +1 -1
- package/dist/source/index.d.ts +2 -0
- package/dist/source/index.jsx +2 -0
- package/dist/source/index.jsx.map +1 -1
- package/dist/source/lazyRouteComponent.jsx +4 -2
- package/dist/source/lazyRouteComponent.jsx.map +1 -1
- package/dist/source/link.jsx +37 -51
- package/dist/source/link.jsx.map +1 -1
- package/dist/source/scroll-restoration.d.ts +8 -1
- package/dist/source/scroll-restoration.jsx +55 -12
- package/dist/source/scroll-restoration.jsx.map +1 -1
- package/dist/source/ssr/RouterClient.d.ts +15 -0
- package/dist/source/ssr/RouterClient.jsx +48 -0
- package/dist/source/ssr/RouterClient.jsx.map +1 -0
- package/dist/source/ssr/RouterServer.d.ts +15 -0
- package/dist/source/ssr/RouterServer.jsx +40 -0
- package/dist/source/ssr/RouterServer.jsx.map +1 -0
- package/dist/source/ssr/client.d.ts +1 -0
- package/dist/source/ssr/client.js +2 -0
- package/dist/source/ssr/client.js.map +1 -0
- package/dist/source/ssr/defaultRenderHandler.d.ts +1 -0
- package/dist/source/ssr/defaultRenderHandler.jsx +9 -0
- package/dist/source/ssr/defaultRenderHandler.jsx.map +1 -0
- package/dist/source/ssr/defaultStreamHandler.d.ts +1 -0
- package/dist/source/ssr/defaultStreamHandler.jsx +10 -0
- package/dist/source/ssr/defaultStreamHandler.jsx.map +1 -0
- package/dist/source/ssr/renderRouterToStream.d.ts +8 -0
- package/dist/source/ssr/renderRouterToStream.jsx +55 -0
- package/dist/source/ssr/renderRouterToStream.jsx.map +1 -0
- package/dist/source/ssr/renderRouterToString.d.ts +7 -0
- package/dist/source/ssr/renderRouterToString.jsx +26 -0
- package/dist/source/ssr/renderRouterToString.jsx.map +1 -0
- package/dist/source/ssr/server.d.ts +6 -0
- package/dist/source/ssr/server.js +7 -0
- package/dist/source/ssr/server.js.map +1 -0
- package/package.json +16 -3
- package/src/Asset.tsx +157 -7
- package/src/Body.tsx +26 -0
- package/src/CatchBoundary.tsx +11 -25
- package/src/Html.tsx +65 -0
- package/src/Match.tsx +135 -58
- package/src/Matches.tsx +16 -4
- package/src/RouterProvider.tsx +6 -0
- package/src/ScriptOnce.tsx +43 -28
- package/src/Scripts.tsx +121 -56
- package/src/Transitioner.tsx +197 -176
- package/src/awaited.tsx +17 -28
- package/src/index.tsx +2 -0
- package/src/lazyRouteComponent.tsx +4 -2
- package/src/link.tsx +42 -47
- package/src/scroll-restoration.tsx +69 -21
- package/src/ssr/RouterClient.tsx +58 -0
- package/src/ssr/RouterServer.tsx +51 -0
- package/src/ssr/client.ts +1 -0
- package/src/ssr/defaultRenderHandler.tsx +12 -0
- package/src/ssr/defaultStreamHandler.tsx +13 -0
- package/src/ssr/renderRouterToStream.tsx +85 -0
- package/src/ssr/renderRouterToString.tsx +37 -0
- package/src/ssr/server.ts +6 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as Vue from 'vue'
|
|
1
2
|
import {
|
|
2
3
|
defaultGetScrollRestorationKey,
|
|
3
4
|
restoreScroll,
|
|
@@ -6,24 +7,71 @@ import {
|
|
|
6
7
|
import { useRouter } from './useRouter'
|
|
7
8
|
import { ScriptOnce } from './ScriptOnce'
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
10
|
+
/**
|
|
11
|
+
* ScrollRestoration component for Vue.
|
|
12
|
+
* On server: renders a ScriptOnce with scroll restoration logic.
|
|
13
|
+
* On client during hydration: renders a matching ScriptOnce to avoid mismatch.
|
|
14
|
+
* After mount: renders nothing.
|
|
15
|
+
*/
|
|
16
|
+
export const ScrollRestoration = Vue.defineComponent({
|
|
17
|
+
name: 'ScrollRestoration',
|
|
18
|
+
setup() {
|
|
19
|
+
const router = useRouter()
|
|
20
|
+
|
|
21
|
+
// Track mounted state for hydration handling
|
|
22
|
+
const mounted = Vue.ref(false)
|
|
23
|
+
Vue.onMounted(() => {
|
|
24
|
+
mounted.value = true
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
return () => {
|
|
28
|
+
// After mount, render nothing
|
|
29
|
+
if (mounted.value) {
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Check if scroll restoration is enabled
|
|
34
|
+
if (!router.isScrollRestoring) {
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Check custom scroll restoration function
|
|
39
|
+
if (typeof router.options.scrollRestoration === 'function') {
|
|
40
|
+
const shouldRestore = router.options.scrollRestoration({
|
|
41
|
+
location: router.latestLocation,
|
|
42
|
+
})
|
|
43
|
+
if (!shouldRestore) {
|
|
44
|
+
return null
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const getKey =
|
|
49
|
+
router.options.getScrollRestorationKey || defaultGetScrollRestorationKey
|
|
50
|
+
const userKey = getKey(router.latestLocation)
|
|
51
|
+
const resolvedKey =
|
|
52
|
+
userKey !== defaultGetScrollRestorationKey(router.latestLocation)
|
|
53
|
+
? userKey
|
|
54
|
+
: undefined
|
|
55
|
+
|
|
56
|
+
const restoreScrollOptions: Parameters<typeof restoreScroll>[0] = {
|
|
57
|
+
storageKey,
|
|
58
|
+
shouldScrollRestoration: true,
|
|
59
|
+
}
|
|
60
|
+
if (resolvedKey) {
|
|
61
|
+
restoreScrollOptions.key = resolvedKey
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Server-side: render the actual scroll restoration script
|
|
65
|
+
if (router.isServer) {
|
|
66
|
+
return (
|
|
67
|
+
<ScriptOnce
|
|
68
|
+
children={`(${restoreScroll.toString()})(${JSON.stringify(restoreScrollOptions)})`}
|
|
69
|
+
/>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Client-side during hydration: render empty ScriptOnce to match server structure
|
|
74
|
+
return <ScriptOnce children="" />
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as Vue from 'vue'
|
|
2
|
+
import { hydrate } from '@tanstack/router-core/ssr/client'
|
|
3
|
+
import { HeadContent } from '../HeadContent'
|
|
4
|
+
import { RouterProvider } from '../RouterProvider'
|
|
5
|
+
import type { AnyRouter } from '@tanstack/router-core'
|
|
6
|
+
|
|
7
|
+
let hydrationPromise: Promise<void | Array<Array<void>>> | undefined
|
|
8
|
+
|
|
9
|
+
export const RouterClient = Vue.defineComponent({
|
|
10
|
+
name: 'RouterClient',
|
|
11
|
+
props: {
|
|
12
|
+
router: {
|
|
13
|
+
type: Object as () => AnyRouter,
|
|
14
|
+
required: true,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
setup(props) {
|
|
18
|
+
const isHydrated = Vue.ref(false)
|
|
19
|
+
|
|
20
|
+
if (!hydrationPromise) {
|
|
21
|
+
if (!props.router.state.matches.length) {
|
|
22
|
+
hydrationPromise = hydrate(props.router)
|
|
23
|
+
} else {
|
|
24
|
+
hydrationPromise = Promise.resolve()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Vue.onMounted(() => {
|
|
29
|
+
hydrationPromise!.then(() => {
|
|
30
|
+
isHydrated.value = true
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
// For SSR, we're already hydrated
|
|
35
|
+
if (typeof window === 'undefined') {
|
|
36
|
+
isHydrated.value = true
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return () => {
|
|
40
|
+
if (!isHydrated.value) {
|
|
41
|
+
return null
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return Vue.h(
|
|
45
|
+
RouterProvider,
|
|
46
|
+
{
|
|
47
|
+
router: props.router,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
innerWrap: (innerProps: { children: any }) => [
|
|
51
|
+
Vue.h(HeadContent),
|
|
52
|
+
innerProps.children,
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
})
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as Vue from 'vue'
|
|
2
|
+
import { Asset } from '../Asset'
|
|
3
|
+
import { useTags } from '../HeadContent'
|
|
4
|
+
import { RouterProvider } from '../RouterProvider'
|
|
5
|
+
import { Scripts } from '../Scripts'
|
|
6
|
+
import type { AnyRouter, RouterManagedTag } from '@tanstack/router-core'
|
|
7
|
+
|
|
8
|
+
const ServerHeadContent = Vue.defineComponent({
|
|
9
|
+
name: 'ServerHeadContent',
|
|
10
|
+
setup() {
|
|
11
|
+
const getTags = useTags()
|
|
12
|
+
|
|
13
|
+
return () =>
|
|
14
|
+
getTags().map((tag: RouterManagedTag) =>
|
|
15
|
+
Vue.h(Asset, { key: tag.tag + (tag as any).id, ...tag }),
|
|
16
|
+
)
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
export const RouterServer = Vue.defineComponent({
|
|
21
|
+
name: 'RouterServer',
|
|
22
|
+
props: {
|
|
23
|
+
router: {
|
|
24
|
+
type: Object as () => AnyRouter,
|
|
25
|
+
required: true,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
setup(props) {
|
|
29
|
+
return () =>
|
|
30
|
+
Vue.h('html', null, [
|
|
31
|
+
Vue.h('head', null, [Vue.h(ServerHeadContent)]),
|
|
32
|
+
Vue.h('body', null, [
|
|
33
|
+
Vue.h('div', { id: '__app' }, [
|
|
34
|
+
Vue.h(
|
|
35
|
+
RouterProvider,
|
|
36
|
+
{
|
|
37
|
+
router: props.router,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
innerWrap: (innerProps: { children: any }) => [
|
|
41
|
+
Vue.h(ServerHeadContent),
|
|
42
|
+
innerProps.children,
|
|
43
|
+
Vue.h(Scripts),
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
),
|
|
47
|
+
]),
|
|
48
|
+
]),
|
|
49
|
+
])
|
|
50
|
+
},
|
|
51
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RouterClient } from './RouterClient'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineHandlerCallback } from '@tanstack/router-core/ssr/server'
|
|
2
|
+
import { renderRouterToString } from './renderRouterToString'
|
|
3
|
+
import { RouterServer } from './RouterServer'
|
|
4
|
+
|
|
5
|
+
export const defaultRenderHandler = defineHandlerCallback(
|
|
6
|
+
({ router, responseHeaders }) =>
|
|
7
|
+
renderRouterToString({
|
|
8
|
+
router,
|
|
9
|
+
responseHeaders,
|
|
10
|
+
App: RouterServer,
|
|
11
|
+
}),
|
|
12
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineHandlerCallback } from '@tanstack/router-core/ssr/server'
|
|
2
|
+
import { renderRouterToStream } from './renderRouterToStream'
|
|
3
|
+
import { RouterServer } from './RouterServer'
|
|
4
|
+
|
|
5
|
+
export const defaultStreamHandler = defineHandlerCallback(
|
|
6
|
+
async ({ request, router, responseHeaders }) =>
|
|
7
|
+
await renderRouterToStream({
|
|
8
|
+
request,
|
|
9
|
+
router,
|
|
10
|
+
responseHeaders,
|
|
11
|
+
App: RouterServer,
|
|
12
|
+
}),
|
|
13
|
+
)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ReadableStream as NodeReadableStream } from 'node:stream/web'
|
|
2
|
+
import * as Vue from 'vue'
|
|
3
|
+
import { pipeToWebWritable, renderToString } from 'vue/server-renderer'
|
|
4
|
+
import { isbot } from 'isbot'
|
|
5
|
+
import { transformReadableStreamWithRouter } from '@tanstack/router-core/ssr/server'
|
|
6
|
+
import type { AnyRouter } from '@tanstack/router-core'
|
|
7
|
+
import type { Component } from 'vue'
|
|
8
|
+
import type { ReadableStream } from 'node:stream/web'
|
|
9
|
+
|
|
10
|
+
function prependDoctype(
|
|
11
|
+
readable: globalThis.ReadableStream,
|
|
12
|
+
): NodeReadableStream<Uint8Array> {
|
|
13
|
+
const encoder = new TextEncoder()
|
|
14
|
+
let sentDoctype = false
|
|
15
|
+
|
|
16
|
+
return new NodeReadableStream<Uint8Array>({
|
|
17
|
+
async start(controller) {
|
|
18
|
+
const reader = readable.getReader()
|
|
19
|
+
|
|
20
|
+
async function pump(): Promise<void> {
|
|
21
|
+
const { done, value } = await reader.read()
|
|
22
|
+
if (done) {
|
|
23
|
+
controller.close()
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!sentDoctype) {
|
|
28
|
+
sentDoctype = true
|
|
29
|
+
controller.enqueue(encoder.encode('<!DOCTYPE html>'))
|
|
30
|
+
}
|
|
31
|
+
controller.enqueue(value)
|
|
32
|
+
return pump()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pump().catch((err) => controller.error(err))
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const renderRouterToStream = async ({
|
|
41
|
+
request,
|
|
42
|
+
router,
|
|
43
|
+
responseHeaders,
|
|
44
|
+
App,
|
|
45
|
+
}: {
|
|
46
|
+
request: Request
|
|
47
|
+
router: AnyRouter
|
|
48
|
+
responseHeaders: Headers
|
|
49
|
+
App: Component
|
|
50
|
+
}) => {
|
|
51
|
+
const app = Vue.createSSRApp(App, { router })
|
|
52
|
+
|
|
53
|
+
if (isbot(request.headers.get('User-Agent'))) {
|
|
54
|
+
let fullHtml = await renderToString(app)
|
|
55
|
+
|
|
56
|
+
const htmlOpenIndex = fullHtml.indexOf('<html')
|
|
57
|
+
const htmlCloseIndex = fullHtml.indexOf('</html>')
|
|
58
|
+
|
|
59
|
+
if (htmlOpenIndex !== -1 && htmlCloseIndex !== -1) {
|
|
60
|
+
fullHtml = fullHtml.slice(htmlOpenIndex, htmlCloseIndex + 7)
|
|
61
|
+
} else if (htmlOpenIndex !== -1) {
|
|
62
|
+
fullHtml = fullHtml.slice(htmlOpenIndex)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return new Response(`<!DOCTYPE html>${fullHtml}`, {
|
|
66
|
+
status: router.state.statusCode,
|
|
67
|
+
headers: responseHeaders,
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const { writable, readable } = new TransformStream()
|
|
72
|
+
|
|
73
|
+
pipeToWebWritable(app, {}, writable)
|
|
74
|
+
|
|
75
|
+
const doctypedStream = prependDoctype(readable)
|
|
76
|
+
const responseStream = transformReadableStreamWithRouter(
|
|
77
|
+
router,
|
|
78
|
+
doctypedStream as unknown as ReadableStream,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
return new Response(responseStream as any, {
|
|
82
|
+
status: router.state.statusCode,
|
|
83
|
+
headers: responseHeaders,
|
|
84
|
+
})
|
|
85
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as Vue from 'vue'
|
|
2
|
+
import { renderToString as vueRenderToString } from 'vue/server-renderer'
|
|
3
|
+
import type { AnyRouter } from '@tanstack/router-core'
|
|
4
|
+
import type { Component } from 'vue'
|
|
5
|
+
|
|
6
|
+
export const renderRouterToString = async ({
|
|
7
|
+
router,
|
|
8
|
+
responseHeaders,
|
|
9
|
+
App,
|
|
10
|
+
}: {
|
|
11
|
+
router: AnyRouter
|
|
12
|
+
responseHeaders: Headers
|
|
13
|
+
App: Component
|
|
14
|
+
}) => {
|
|
15
|
+
try {
|
|
16
|
+
const app = Vue.createSSRApp(App, { router })
|
|
17
|
+
|
|
18
|
+
let html = await vueRenderToString(app)
|
|
19
|
+
router.serverSsr!.setRenderFinished()
|
|
20
|
+
const injectedHtml = await Promise.all(router.serverSsr!.injectedHtml).then(
|
|
21
|
+
(htmls) => htmls.join(''),
|
|
22
|
+
)
|
|
23
|
+
html = html.replace(`</body>`, () => `${injectedHtml}</body>`)
|
|
24
|
+
return new Response(`<!DOCTYPE html>${html}`, {
|
|
25
|
+
status: router.state.statusCode,
|
|
26
|
+
headers: responseHeaders,
|
|
27
|
+
})
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error('Render to string error:', error)
|
|
30
|
+
return new Response('Internal Server Error', {
|
|
31
|
+
status: 500,
|
|
32
|
+
headers: responseHeaders,
|
|
33
|
+
})
|
|
34
|
+
} finally {
|
|
35
|
+
router.serverSsr?.cleanup()
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { RouterServer } from './RouterServer'
|
|
2
|
+
export { defaultRenderHandler } from './defaultRenderHandler'
|
|
3
|
+
export { defaultStreamHandler } from './defaultStreamHandler'
|
|
4
|
+
export { renderRouterToStream } from './renderRouterToStream'
|
|
5
|
+
export { renderRouterToString } from './renderRouterToString'
|
|
6
|
+
export * from '@tanstack/router-core/ssr/server'
|