2023-04-12 17:10:18 +00:00
|
|
|
import { defineComponent, getCurrentInstance, onErrorCaptured, ref } from 'vue'
|
2023-04-07 16:02:47 +00:00
|
|
|
import { ssrRenderAttrs, ssrRenderSlot, ssrRenderVNode } from 'vue/server-renderer'
|
2023-04-12 17:10:18 +00:00
|
|
|
import { useState } from '../composables/state'
|
2023-03-08 21:13:06 +00:00
|
|
|
import { createBuffer } from './utils'
|
|
|
|
|
|
|
|
const NuxtClientFallbackServer = defineComponent({
|
|
|
|
name: 'NuxtClientFallback',
|
|
|
|
inheritAttrs: false,
|
|
|
|
props: {
|
|
|
|
uid: {
|
|
|
|
type: String
|
|
|
|
},
|
|
|
|
fallbackTag: {
|
|
|
|
type: String,
|
|
|
|
default: () => 'div'
|
|
|
|
},
|
|
|
|
fallback: {
|
|
|
|
type: String,
|
|
|
|
default: () => ''
|
|
|
|
},
|
|
|
|
placeholder: {
|
|
|
|
type: String
|
|
|
|
},
|
|
|
|
placeholderTag: {
|
|
|
|
type: String
|
2023-05-14 21:22:54 +00:00
|
|
|
},
|
|
|
|
keepFallback: {
|
|
|
|
type: Boolean,
|
|
|
|
default: () => false
|
2023-03-08 21:13:06 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
emits: ['ssr-error'],
|
|
|
|
setup (props, ctx) {
|
|
|
|
const vm = getCurrentInstance()
|
|
|
|
const ssrFailed = ref(false)
|
|
|
|
|
|
|
|
onErrorCaptured(() => {
|
|
|
|
useState(`${props.uid}`, () => true)
|
|
|
|
ssrFailed.value = true
|
|
|
|
ctx.emit('ssr-error')
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
|
|
|
|
try {
|
|
|
|
const defaultSlot = ctx.slots.default?.()
|
|
|
|
const ssrVNodes = createBuffer()
|
|
|
|
|
2023-04-12 17:10:18 +00:00
|
|
|
for (let i = 0; i < (defaultSlot?.length || 0); i++) {
|
|
|
|
ssrRenderVNode(ssrVNodes.push, defaultSlot![i], vm!)
|
2023-03-08 21:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return { ssrFailed, ssrVNodes }
|
|
|
|
} catch {
|
|
|
|
// catch in dev
|
|
|
|
useState(`${props.uid}`, () => true)
|
|
|
|
ctx.emit('ssr-error')
|
|
|
|
return { ssrFailed: true, ssrVNodes: [] }
|
|
|
|
}
|
|
|
|
},
|
2023-04-12 17:10:18 +00:00
|
|
|
ssrRender (ctx: any, push: any, parent: any) {
|
2023-03-08 21:13:06 +00:00
|
|
|
if (ctx.ssrFailed) {
|
|
|
|
const { fallback, placeholder } = ctx.$slots
|
|
|
|
if (fallback || placeholder) {
|
|
|
|
ssrRenderSlot(ctx.$slots, fallback ? 'fallback' : 'placeholder', {}, null, push, parent)
|
|
|
|
} else {
|
|
|
|
const content = ctx.placeholder || ctx.fallback
|
|
|
|
const tag = ctx.placeholderTag || ctx.fallbackTag
|
|
|
|
push(`<${tag}${ssrRenderAttrs(ctx.$attrs)}>${content}</${tag}>`)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// push Fragment markup
|
|
|
|
push('<!--[-->')
|
|
|
|
push(ctx.ssrVNodes.getBuffer())
|
|
|
|
push('<!--]-->')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
export default NuxtClientFallbackServer
|