feat(ssr): serverPrefetch
This commit is contained in:
parent
63f1f18064
commit
c73b4a0e10
@ -103,6 +103,7 @@ export interface ComponentOptionsBase<
|
|||||||
directives?: Record<string, Directive>
|
directives?: Record<string, Directive>
|
||||||
inheritAttrs?: boolean
|
inheritAttrs?: boolean
|
||||||
emits?: (E | EE[]) & ThisType<void>
|
emits?: (E | EE[]) & ThisType<void>
|
||||||
|
serverPrefetch?(): Promise<any>
|
||||||
|
|
||||||
// Internal ------------------------------------------------------------------
|
// Internal ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import { renderToStream as _renderToStream } from '../src/renderToStream'
|
|||||||
import { Readable } from 'stream'
|
import { Readable } from 'stream'
|
||||||
import { ssrRenderSlot } from '../src/helpers/ssrRenderSlot'
|
import { ssrRenderSlot } from '../src/helpers/ssrRenderSlot'
|
||||||
import { ssrRenderComponent } from '../src/helpers/ssrRenderComponent'
|
import { ssrRenderComponent } from '../src/helpers/ssrRenderComponent'
|
||||||
|
|
||||||
const promisifyStream = (stream: Readable) => {
|
const promisifyStream = (stream: Readable) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let result = ''
|
let result = ''
|
||||||
@ -599,4 +600,23 @@ describe('ssr: renderToStream', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('serverPrefetch', async () => {
|
||||||
|
const msg = Promise.resolve('hello')
|
||||||
|
const app = createApp({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
msg: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async serverPrefetch() {
|
||||||
|
this.msg = await msg
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return h('div', this.msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const html = await renderToStream(app)
|
||||||
|
expect(html).toBe(`<div>hello</div>`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -14,6 +14,7 @@ import { escapeHtml } from '@vue/shared'
|
|||||||
import { renderToString } from '../src/renderToString'
|
import { renderToString } from '../src/renderToString'
|
||||||
import { ssrRenderSlot, SSRSlot } from '../src/helpers/ssrRenderSlot'
|
import { ssrRenderSlot, SSRSlot } from '../src/helpers/ssrRenderSlot'
|
||||||
import { ssrRenderComponent } from '../src/helpers/ssrRenderComponent'
|
import { ssrRenderComponent } from '../src/helpers/ssrRenderComponent'
|
||||||
|
|
||||||
describe('ssr: renderToString', () => {
|
describe('ssr: renderToString', () => {
|
||||||
test('should apply app context', async () => {
|
test('should apply app context', async () => {
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
@ -580,4 +581,23 @@ describe('ssr: renderToString', () => {
|
|||||||
).toHaveBeenWarned()
|
).toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('serverPrefetch', async () => {
|
||||||
|
const msg = Promise.resolve('hello')
|
||||||
|
const app = createApp({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
msg: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async serverPrefetch() {
|
||||||
|
this.msg = await msg
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return h('div', this.msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const html = await renderToString(app)
|
||||||
|
expect(html).toBe(`<div>hello</div>`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -2,6 +2,7 @@ import {
|
|||||||
Comment,
|
Comment,
|
||||||
Component,
|
Component,
|
||||||
ComponentInternalInstance,
|
ComponentInternalInstance,
|
||||||
|
ComponentOptions,
|
||||||
DirectiveBinding,
|
DirectiveBinding,
|
||||||
Fragment,
|
Fragment,
|
||||||
mergeProps,
|
mergeProps,
|
||||||
@ -84,12 +85,20 @@ export function renderComponentVNode(
|
|||||||
): SSRBuffer | Promise<SSRBuffer> {
|
): SSRBuffer | Promise<SSRBuffer> {
|
||||||
const instance = createComponentInstance(vnode, parentComponent, null)
|
const instance = createComponentInstance(vnode, parentComponent, null)
|
||||||
const res = setupComponent(instance, true /* isSSR */)
|
const res = setupComponent(instance, true /* isSSR */)
|
||||||
if (isPromise(res)) {
|
const hasAsyncSetup = isPromise(res)
|
||||||
return res
|
const prefetch = (vnode.type as ComponentOptions).serverPrefetch
|
||||||
.catch(err => {
|
if (hasAsyncSetup || prefetch) {
|
||||||
warn(`[@vue/server-renderer]: Uncaught error in async setup:\n`, err)
|
let p = hasAsyncSetup
|
||||||
|
? (res as Promise<void>).catch(err => {
|
||||||
|
warn(`[@vue/server-renderer]: Uncaught error in async setup:\n`, err)
|
||||||
|
})
|
||||||
|
: Promise.resolve()
|
||||||
|
if (prefetch) {
|
||||||
|
p = p.then(() => prefetch.call(instance.proxy)).catch(err => {
|
||||||
|
warn(`[@vue/server-renderer]: Uncaught error in serverPrefetch:\n`, err)
|
||||||
})
|
})
|
||||||
.then(() => renderComponentSubTree(instance))
|
}
|
||||||
|
return p.then(() => renderComponentSubTree(instance))
|
||||||
} else {
|
} else {
|
||||||
return renderComponentSubTree(instance)
|
return renderComponentSubTree(instance)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user