mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
fix(nuxt): import and wrap client-only components once (#7245)
This commit is contained in:
parent
d115b01a35
commit
96b5b8fd6d
@ -19,38 +19,39 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
export function createClientOnly (component) {
|
||||
const { setup, render: _render, template: _template } = component
|
||||
if (_render) {
|
||||
const clone = { ...component }
|
||||
|
||||
if (clone.render) {
|
||||
// override the component render (non script setup component)
|
||||
component.render = (ctx, ...args) => {
|
||||
clone.render = (ctx, ...args) => {
|
||||
return ctx.mounted$
|
||||
? h(Fragment, null, [h(_render(ctx, ...args), ctx.$attrs ?? ctx._.attrs)])
|
||||
? h(Fragment, ctx.$attrs ?? ctx._.attrs, component.render(ctx, ...args))
|
||||
: h('div', ctx.$attrs ?? ctx._.attrs)
|
||||
}
|
||||
} else if (_template) {
|
||||
} else if (clone.template) {
|
||||
// handle runtime-compiler template
|
||||
component.template = `
|
||||
<template v-if="mounted$">${_template}</template>
|
||||
clone.template = `
|
||||
<template v-if="mounted$">${component.template}</template>
|
||||
<template v-else><div></div></template>
|
||||
`
|
||||
}
|
||||
return defineComponent({
|
||||
...component,
|
||||
setup (props, ctx) {
|
||||
|
||||
clone.setup = (props, ctx) => {
|
||||
const mounted$ = ref(false)
|
||||
onMounted(() => { mounted$.value = true })
|
||||
|
||||
return Promise.resolve(setup?.(props, ctx) || {})
|
||||
return Promise.resolve(component.setup?.(props, ctx) || {})
|
||||
.then((setupState) => {
|
||||
return typeof setupState !== 'function'
|
||||
? { ...setupState, mounted$ }
|
||||
: (...args) => {
|
||||
return mounted$.value
|
||||
// use Fragment to avoid oldChildren is null issue
|
||||
? h(Fragment, null, [h(setupState(...args), ctx.attrs)])
|
||||
? h(Fragment, ctx.attrs, setupState(...args))
|
||||
: h('div', ctx.attrs)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return clone
|
||||
}
|
||||
|
@ -68,20 +68,24 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => {
|
||||
s.replace(/(?<=[ (])_?resolveComponent\(\s*["'](lazy-|Lazy)?([^'"]*?)["'][\s,]*\)/g, (full, lazy, name) => {
|
||||
const component = findComponent(components, name, options.mode)
|
||||
if (component) {
|
||||
const identifier = map.get(component) || `__nuxt_component_${num++}`
|
||||
let identifier = map.get(component) || `__nuxt_component_${num++}`
|
||||
map.set(component, identifier)
|
||||
|
||||
if (lazy) {
|
||||
imports.add(genImport('vue', [{ name: 'defineAsyncComponent', as: '__defineAsyncComponent' }]))
|
||||
identifier += '_lazy'
|
||||
imports.add(`const ${identifier} = /*#__PURE__*/ __defineAsyncComponent(${genDynamicImport(component.filePath)})`)
|
||||
} else {
|
||||
imports.add(genImport(component.filePath, [{ name: component.export, as: identifier }]))
|
||||
}
|
||||
|
||||
const isClientOnly = component.mode === 'client'
|
||||
if (isClientOnly) {
|
||||
imports.add(genImport('#app/components/client-only', [{ name: 'createClientOnly' }]))
|
||||
imports.add(`const ${identifier}_client = /*#__PURE__*/ createClientOnly(${identifier})`)
|
||||
identifier += '_client'
|
||||
}
|
||||
if (lazy) {
|
||||
imports.add(genImport('vue', [{ name: 'defineAsyncComponent', as: '__defineAsyncComponent' }]))
|
||||
imports.add(`const ${identifier}_lazy = /*#__PURE__*/ __defineAsyncComponent(${genDynamicImport(component.filePath)})`)
|
||||
return isClientOnly ? `/*#__PURE__*/ createClientOnly(${identifier}_lazy)` : `${identifier}_lazy`
|
||||
} else {
|
||||
imports.add(genImport(component.filePath, [{ name: component.export, as: identifier }]))
|
||||
return isClientOnly ? `/*#__PURE__*/ createClientOnly(${identifier})` : identifier
|
||||
}
|
||||
return identifier
|
||||
}
|
||||
// no matched
|
||||
return full
|
||||
|
Loading…
Reference in New Issue
Block a user