Skip to content

Commit

Permalink
fix(ssr): call mixed in serverPrefetch hooks(fix: vuejs#2889)
Browse files Browse the repository at this point in the history
  • Loading branch information
tabjy committed Dec 31, 2020
1 parent c105699 commit 5b38902
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 11 deletions.
6 changes: 4 additions & 2 deletions packages/runtime-core/src/apiLifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,17 @@ export function injectHook(
export const createHook = <T extends Function = () => any>(
lifecycle: LifecycleHooks
) => (hook: T, target: ComponentInternalInstance | null = currentInstance) =>
// post-create lifecycle registrations are noops during SSR
!isInSSRComponentSetup && injectHook(lifecycle, hook, target)
// post-create lifecycle registrations are noops during SSR (except for serverPrefetch)
(!isInSSRComponentSetup || lifecycle === LifecycleHooks.SERVER_PREFETCH) &&
injectHook(lifecycle, hook, target)

export const onBeforeMount = createHook(LifecycleHooks.BEFORE_MOUNT)
export const onMounted = createHook(LifecycleHooks.MOUNTED)
export const onBeforeUpdate = createHook(LifecycleHooks.BEFORE_UPDATE)
export const onUpdated = createHook(LifecycleHooks.UPDATED)
export const onBeforeUnmount = createHook(LifecycleHooks.BEFORE_UNMOUNT)
export const onUnmounted = createHook(LifecycleHooks.UNMOUNTED)
export const onServerPrefetch = createHook(LifecycleHooks.SERVER_PREFETCH)

export type DebuggerHook = (e: DebuggerEvent) => void
export const onRenderTriggered = createHook<DebuggerHook>(
Expand Down
10 changes: 8 additions & 2 deletions packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ export const enum LifecycleHooks {
ACTIVATED = 'a',
RENDER_TRIGGERED = 'rtg',
RENDER_TRACKED = 'rtc',
ERROR_CAPTURED = 'ec'
ERROR_CAPTURED = 'ec',
SERVER_PREFETCH = 'sp'
}

export interface SetupContext<E = EmitsOptions> {
Expand Down Expand Up @@ -396,6 +397,10 @@ export interface ComponentInternalInstance {
* @internal
*/
[LifecycleHooks.ERROR_CAPTURED]: LifecycleHook
/**
* @internal
*/
[LifecycleHooks.SERVER_PREFETCH]: LifecycleHook
}

const emptyAppContext = createAppContext()
Expand Down Expand Up @@ -476,7 +481,8 @@ export function createComponentInstance(
a: null,
rtg: null,
rtc: null,
ec: null
ec: null,
sp: null
}
if (__DEV__) {
instance.ctx = createRenderContext(instance)
Expand Down
5 changes: 5 additions & 0 deletions packages/runtime-core/src/componentOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
onActivated,
onDeactivated,
onRenderTriggered,
onServerPrefetch,
DebuggerHook,
ErrorCapturedHook
} from './apiLifecycle'
Expand Down Expand Up @@ -504,6 +505,7 @@ export function applyOptions(
renderTracked,
renderTriggered,
errorCaptured,
serverPrefetch,
// public API
expose
} = options
Expand Down Expand Up @@ -781,6 +783,9 @@ export function applyOptions(
if (unmounted) {
onUnmounted(unmounted.bind(publicThis))
}
if (serverPrefetch) {
onServerPrefetch(serverPrefetch.bind(publicThis))
}

if (isArray(expose)) {
if (!asMixin) {
Expand Down
21 changes: 14 additions & 7 deletions packages/server-renderer/src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
Comment,
Component,
ComponentInternalInstance,
ComponentOptions,
DirectiveBinding,
Fragment,
mergeProps,
Expand Down Expand Up @@ -85,17 +84,25 @@ export function renderComponentVNode(
const instance = createComponentInstance(vnode, parentComponent, null)
const res = setupComponent(instance, true /* isSSR */)
const hasAsyncSetup = isPromise(res)
const prefetch = (vnode.type as ComponentOptions).serverPrefetch
if (hasAsyncSetup || prefetch) {
const prefetches = instance.sp
if (hasAsyncSetup || prefetches) {
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)
})
if (prefetches) {
p = p
.then(() =>
Promise.all(prefetches.map(prefetch => prefetch.call(instance.proxy)))
)
.then(() => undefined)
.catch(err => {
warn(
`[@vue/server-renderer]: Uncaught error in serverPrefetch:\n`,
err
)
})
}
return p.then(() => renderComponentSubTree(instance))
} else {
Expand Down

0 comments on commit 5b38902

Please sign in to comment.