Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

Commit

Permalink
refactor: split server/client part
Browse files Browse the repository at this point in the history
  • Loading branch information
huang-julien committed Mar 7, 2023
1 parent ba30fb2 commit e1212f2
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 121 deletions.
46 changes: 46 additions & 0 deletions packages/nuxt/src/app/components/client-fallback.client.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { defineComponent, createElementBlock } from 'vue'

export default defineComponent({
name: 'ClientFallback',
inheritAttrs: false,
props: {
uid: {
type: String
},
fallbackTag: {
type: String,
default: () => 'div'
},
fallback: {
type: String,
default: () => ''
},
placeholder: {
type: String
},
placeholderTag: {
type: String
}
},
emits: ['ssr-error'],
setup (props, ctx) {
const mounted = ref(false)
const ssrFailed = useState(`${props.uid}`)

if (ssrFailed.value) {
onMounted(() => { mounted.value = true })
}

return () => {
if (mounted.value) { return ctx.slots.default?.() }
if (ssrFailed.value) {
const slot = ctx.slots.placeholder || ctx.slots.fallback
if (slot) { return slot() }
const fallbackStr = props.placeholder || props.fallback
const fallbackTag = props.placeholderTag || props.fallbackTag
return createElementBlock(fallbackTag, null, fallbackStr)
}
return ctx.slots.default?.()
}
}
})
119 changes: 0 additions & 119 deletions packages/nuxt/src/app/components/client-fallback.mjs

This file was deleted.

74 changes: 74 additions & 0 deletions packages/nuxt/src/app/components/client-fallback.server.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { defineComponent, getCurrentInstance, onErrorCaptured } from 'vue'
import { ssrRenderVNode, ssrRenderAttrs, ssrRenderSlot } from 'vue/server-renderer'
import { createBuffer } from './utils'

const ClientFallbackServer = defineComponent({
name: 'ClientFallback',
inheritAttrs: false,
props: {
uid: {
type: String
},
fallbackTag: {
type: String,
default: () => 'div'
},
fallback: {
type: String,
default: () => ''
},
placeholder: {
type: String
},
placeholderTag: {
type: String
}
},
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()

for (let i = 0; i < defaultSlot.length; i++) {
ssrRenderVNode(ssrVNodes.push, defaultSlot[i], vm)
}

return { ssrFailed, ssrVNodes }
} catch {
// catch in dev
useState(`${props.uid}`, () => true)
ctx.emit('ssr-error')
return { ssrFailed: true, ssrVNodes: [] }
}
},
ssrRender (ctx, push, parent) {
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 ClientFallbackServer
2 changes: 1 addition & 1 deletion packages/nuxt/src/components/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => {
return identifier
}

const isClientOnly = component.mode === 'client'
const isClientOnly = component.mode === 'client' && component.pascalName !== 'ClientFallback'
if (isClientOnly) {
imports.add(genImport('#app/components/client-only', [{ name: 'createClientOnly' }]))
identifier += '_client'
Expand Down
9 changes: 8 additions & 1 deletion packages/nuxt/src/core/nuxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,14 @@ async function initNuxt (nuxt: Nuxt) {
// Add <ClientFallback>
addComponent({
name: 'ClientFallback',
filePath: resolve(nuxt.options.appDir, 'components/client-fallback')
filePath: resolve(nuxt.options.appDir, 'components/client-fallback.client'),
mode: 'client'
})

addComponent({
name: 'ClientFallback',
filePath: resolve(nuxt.options.appDir, 'components/client-fallback.server'),
mode: 'server'
})

// Add <NuxtIsland>
Expand Down

0 comments on commit e1212f2

Please sign in to comment.