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

Commit 96b5b8f

Browse files
authored
fix(nuxt): import and wrap client-only components once (#7245)
1 parent d115b01 commit 96b5b8f

2 files changed

Lines changed: 37 additions & 32 deletions

File tree

packages/nuxt/src/app/components/client-only.mjs

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,39 @@ export default defineComponent({
1919
})
2020

2121
export function createClientOnly (component) {
22-
const { setup, render: _render, template: _template } = component
23-
if (_render) {
22+
const clone = { ...component }
23+
24+
if (clone.render) {
2425
// override the component render (non script setup component)
25-
component.render = (ctx, ...args) => {
26+
clone.render = (ctx, ...args) => {
2627
return ctx.mounted$
27-
? h(Fragment, null, [h(_render(ctx, ...args), ctx.$attrs ?? ctx._.attrs)])
28+
? h(Fragment, ctx.$attrs ?? ctx._.attrs, component.render(ctx, ...args))
2829
: h('div', ctx.$attrs ?? ctx._.attrs)
2930
}
30-
} else if (_template) {
31+
} else if (clone.template) {
3132
// handle runtime-compiler template
32-
component.template = `
33-
<template v-if="mounted$">${_template}</template>
33+
clone.template = `
34+
<template v-if="mounted$">${component.template}</template>
3435
<template v-else><div></div></template>
3536
`
3637
}
37-
return defineComponent({
38-
...component,
39-
setup (props, ctx) {
40-
const mounted$ = ref(false)
41-
onMounted(() => { mounted$.value = true })
4238

43-
return Promise.resolve(setup?.(props, ctx) || {})
44-
.then((setupState) => {
45-
return typeof setupState !== 'function'
46-
? { ...setupState, mounted$ }
47-
: (...args) => {
48-
return mounted$.value
39+
clone.setup = (props, ctx) => {
40+
const mounted$ = ref(false)
41+
onMounted(() => { mounted$.value = true })
42+
43+
return Promise.resolve(component.setup?.(props, ctx) || {})
44+
.then((setupState) => {
45+
return typeof setupState !== 'function'
46+
? { ...setupState, mounted$ }
47+
: (...args) => {
48+
return mounted$.value
4949
// use Fragment to avoid oldChildren is null issue
50-
? h(Fragment, null, [h(setupState(...args), ctx.attrs)])
51-
: h('div', ctx.attrs)
52-
}
53-
})
54-
}
55-
})
50+
? h(Fragment, ctx.attrs, setupState(...args))
51+
: h('div', ctx.attrs)
52+
}
53+
})
54+
}
55+
56+
return clone
5657
}

packages/nuxt/src/components/loader.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,24 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => {
6868
s.replace(/(?<=[ (])_?resolveComponent\(\s*["'](lazy-|Lazy)?([^'"]*?)["'][\s,]*\)/g, (full, lazy, name) => {
6969
const component = findComponent(components, name, options.mode)
7070
if (component) {
71-
const identifier = map.get(component) || `__nuxt_component_${num++}`
71+
let identifier = map.get(component) || `__nuxt_component_${num++}`
7272
map.set(component, identifier)
73-
const isClientOnly = component.mode === 'client'
74-
if (isClientOnly) {
75-
imports.add(genImport('#app/components/client-only', [{ name: 'createClientOnly' }]))
76-
}
73+
7774
if (lazy) {
7875
imports.add(genImport('vue', [{ name: 'defineAsyncComponent', as: '__defineAsyncComponent' }]))
79-
imports.add(`const ${identifier}_lazy = /*#__PURE__*/ __defineAsyncComponent(${genDynamicImport(component.filePath)})`)
80-
return isClientOnly ? `/*#__PURE__*/ createClientOnly(${identifier}_lazy)` : `${identifier}_lazy`
76+
identifier += '_lazy'
77+
imports.add(`const ${identifier} = /*#__PURE__*/ __defineAsyncComponent(${genDynamicImport(component.filePath)})`)
8178
} else {
8279
imports.add(genImport(component.filePath, [{ name: component.export, as: identifier }]))
83-
return isClientOnly ? `/*#__PURE__*/ createClientOnly(${identifier})` : identifier
8480
}
81+
82+
const isClientOnly = component.mode === 'client'
83+
if (isClientOnly) {
84+
imports.add(genImport('#app/components/client-only', [{ name: 'createClientOnly' }]))
85+
imports.add(`const ${identifier}_client = /*#__PURE__*/ createClientOnly(${identifier})`)
86+
identifier += '_client'
87+
}
88+
return identifier
8589
}
8690
// no matched
8791
return full

0 commit comments

Comments
 (0)