mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-14 10:04:05 +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) {
|
export function createClientOnly (component) {
|
||||||
const { setup, render: _render, template: _template } = component
|
const clone = { ...component }
|
||||||
if (_render) {
|
|
||||||
|
if (clone.render) {
|
||||||
// override the component render (non script setup component)
|
// override the component render (non script setup component)
|
||||||
component.render = (ctx, ...args) => {
|
clone.render = (ctx, ...args) => {
|
||||||
return ctx.mounted$
|
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)
|
: h('div', ctx.$attrs ?? ctx._.attrs)
|
||||||
}
|
}
|
||||||
} else if (_template) {
|
} else if (clone.template) {
|
||||||
// handle runtime-compiler template
|
// handle runtime-compiler template
|
||||||
component.template = `
|
clone.template = `
|
||||||
<template v-if="mounted$">${_template}</template>
|
<template v-if="mounted$">${component.template}</template>
|
||||||
<template v-else><div></div></template>
|
<template v-else><div></div></template>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
return defineComponent({
|
|
||||||
...component,
|
clone.setup = (props, ctx) => {
|
||||||
setup (props, ctx) {
|
|
||||||
const mounted$ = ref(false)
|
const mounted$ = ref(false)
|
||||||
onMounted(() => { mounted$.value = true })
|
onMounted(() => { mounted$.value = true })
|
||||||
|
|
||||||
return Promise.resolve(setup?.(props, ctx) || {})
|
return Promise.resolve(component.setup?.(props, ctx) || {})
|
||||||
.then((setupState) => {
|
.then((setupState) => {
|
||||||
return typeof setupState !== 'function'
|
return typeof setupState !== 'function'
|
||||||
? { ...setupState, mounted$ }
|
? { ...setupState, mounted$ }
|
||||||
: (...args) => {
|
: (...args) => {
|
||||||
return mounted$.value
|
return mounted$.value
|
||||||
// use Fragment to avoid oldChildren is null issue
|
// 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)
|
: 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) => {
|
s.replace(/(?<=[ (])_?resolveComponent\(\s*["'](lazy-|Lazy)?([^'"]*?)["'][\s,]*\)/g, (full, lazy, name) => {
|
||||||
const component = findComponent(components, name, options.mode)
|
const component = findComponent(components, name, options.mode)
|
||||||
if (component) {
|
if (component) {
|
||||||
const identifier = map.get(component) || `__nuxt_component_${num++}`
|
let identifier = map.get(component) || `__nuxt_component_${num++}`
|
||||||
map.set(component, identifier)
|
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'
|
const isClientOnly = component.mode === 'client'
|
||||||
if (isClientOnly) {
|
if (isClientOnly) {
|
||||||
imports.add(genImport('#app/components/client-only', [{ name: 'createClientOnly' }]))
|
imports.add(genImport('#app/components/client-only', [{ name: 'createClientOnly' }]))
|
||||||
|
imports.add(`const ${identifier}_client = /*#__PURE__*/ createClientOnly(${identifier})`)
|
||||||
|
identifier += '_client'
|
||||||
}
|
}
|
||||||
if (lazy) {
|
return identifier
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// no matched
|
// no matched
|
||||||
return full
|
return full
|
||||||
|
Loading…
Reference in New Issue
Block a user