From 478dd5de79c93a57fed118e376684c9a5383a58a Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Thu, 11 Nov 2021 16:53:25 +0800 Subject: [PATCH 1/9] feat: client only component --- packages/nuxt3/src/app/plugins/client-only.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 packages/nuxt3/src/app/plugins/client-only.ts diff --git a/packages/nuxt3/src/app/plugins/client-only.ts b/packages/nuxt3/src/app/plugins/client-only.ts new file mode 100644 index 00000000000..f16cc2c5906 --- /dev/null +++ b/packages/nuxt3/src/app/plugins/client-only.ts @@ -0,0 +1,16 @@ +import { ref, onMounted, defineComponent } from 'vue' +import { defineNuxtPlugin } from '#app' + +export const ClientOnly = defineComponent({ + setup (_, { slots }) { + const show = ref(false) + onMounted(() => { + show.value = true + }) + return () => (show.value && slots.default ? slots.default() : null) + } +}) + +export default defineNuxtPlugin((nuxtApp) => { + nuxtApp.vueApp.component('ClientOnly', ClientOnly) +}) From aac32eaaf240733eea9d8d780362803445c4bbf5 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Thu, 11 Nov 2021 17:11:16 +0800 Subject: [PATCH 2/9] chore: add plugin --- packages/nuxt3/src/core/templates.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/nuxt3/src/core/templates.ts b/packages/nuxt3/src/core/templates.ts index d1d7613b3af..66f3498d28e 100644 --- a/packages/nuxt3/src/core/templates.ts +++ b/packages/nuxt3/src/core/templates.ts @@ -35,8 +35,10 @@ export const clientPluginTemplate = { getContents (ctx: TemplateContext) { const clientPlugins = ctx.app.plugins.filter(p => !p.mode || p.mode !== 'server') return [ + "import clientOnly from '#app/plugins/client-only'", importSources(clientPlugins.map(p => p.src)), 'export default [', + ' clientOnly,', clientPlugins.map(p => importName(p.src)).join(',\n '), ']' ].join('\n') @@ -49,9 +51,11 @@ export const serverPluginTemplate = { const serverPlugins = ctx.app.plugins.filter(p => !p.mode || p.mode !== 'client') return [ "import preload from '#app/plugins/preload.server'", + "import clientOnly from '#app/plugins/client-only'", importSources(serverPlugins.map(p => p.src)), 'export default [', ' preload,', + ' clientOnly,', serverPlugins.map(p => importName(p.src)).join(',\n '), ']' ].join('\n') From a11dc8fb7bdb26982e2b19d7c37d693a55653fc5 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Thu, 11 Nov 2021 18:30:00 +0800 Subject: [PATCH 3/9] chore: update --- .../nuxt3/src/app/{plugins => components}/client-only.ts | 7 ++----- packages/nuxt3/src/core/nuxt.ts | 6 ++++++ packages/nuxt3/src/core/templates.ts | 4 ---- 3 files changed, 8 insertions(+), 9 deletions(-) rename packages/nuxt3/src/app/{plugins => components}/client-only.ts (56%) diff --git a/packages/nuxt3/src/app/plugins/client-only.ts b/packages/nuxt3/src/app/components/client-only.ts similarity index 56% rename from packages/nuxt3/src/app/plugins/client-only.ts rename to packages/nuxt3/src/app/components/client-only.ts index f16cc2c5906..54a89f4568d 100644 --- a/packages/nuxt3/src/app/plugins/client-only.ts +++ b/packages/nuxt3/src/app/components/client-only.ts @@ -1,7 +1,6 @@ import { ref, onMounted, defineComponent } from 'vue' -import { defineNuxtPlugin } from '#app' -export const ClientOnly = defineComponent({ +const ClientOnly = defineComponent({ setup (_, { slots }) { const show = ref(false) onMounted(() => { @@ -11,6 +10,4 @@ export const ClientOnly = defineComponent({ } }) -export default defineNuxtPlugin((nuxtApp) => { - nuxtApp.vueApp.component('ClientOnly', ClientOnly) -}) +export default ClientOnly diff --git a/packages/nuxt3/src/core/nuxt.ts b/packages/nuxt3/src/core/nuxt.ts index 70fcb2d3122..09e6ffb0e80 100644 --- a/packages/nuxt3/src/core/nuxt.ts +++ b/packages/nuxt3/src/core/nuxt.ts @@ -58,6 +58,12 @@ async function initNuxt (nuxt: Nuxt) { filePath: resolve(nuxt.options.appDir, 'components/nuxt-welcome.vue') }) + // Add + addComponent({ + name: 'clientOnly', + filePath: resolve(nuxt.options.appDir, 'components/client-only.ts') + }) + for (const m of modulesToInstall) { await installModule(nuxt, m) } diff --git a/packages/nuxt3/src/core/templates.ts b/packages/nuxt3/src/core/templates.ts index 66f3498d28e..d1d7613b3af 100644 --- a/packages/nuxt3/src/core/templates.ts +++ b/packages/nuxt3/src/core/templates.ts @@ -35,10 +35,8 @@ export const clientPluginTemplate = { getContents (ctx: TemplateContext) { const clientPlugins = ctx.app.plugins.filter(p => !p.mode || p.mode !== 'server') return [ - "import clientOnly from '#app/plugins/client-only'", importSources(clientPlugins.map(p => p.src)), 'export default [', - ' clientOnly,', clientPlugins.map(p => importName(p.src)).join(',\n '), ']' ].join('\n') @@ -51,11 +49,9 @@ export const serverPluginTemplate = { const serverPlugins = ctx.app.plugins.filter(p => !p.mode || p.mode !== 'client') return [ "import preload from '#app/plugins/preload.server'", - "import clientOnly from '#app/plugins/client-only'", importSources(serverPlugins.map(p => p.src)), 'export default [', ' preload,', - ' clientOnly,', serverPlugins.map(p => importName(p.src)).join(',\n '), ']' ].join('\n') From 49f6e76b7dd80f52497eaf447e4014f78cef5967 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Thu, 11 Nov 2021 18:44:55 +0800 Subject: [PATCH 4/9] chore: update --- .../src/app/components/{client-only.ts => client-only.mjs} | 6 +++++- packages/nuxt3/src/core/nuxt.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) rename packages/nuxt3/src/app/components/{client-only.ts => client-only.mjs} (70%) diff --git a/packages/nuxt3/src/app/components/client-only.ts b/packages/nuxt3/src/app/components/client-only.mjs similarity index 70% rename from packages/nuxt3/src/app/components/client-only.ts rename to packages/nuxt3/src/app/components/client-only.mjs index 54a89f4568d..e5f49b217f8 100644 --- a/packages/nuxt3/src/app/components/client-only.ts +++ b/packages/nuxt3/src/app/components/client-only.mjs @@ -6,7 +6,11 @@ const ClientOnly = defineComponent({ onMounted(() => { show.value = true }) - return () => (show.value && slots.default ? slots.default() : null) + return () => ( + show.value + ? slots.default?.() + : slots.fallback?.() + ) } }) diff --git a/packages/nuxt3/src/core/nuxt.ts b/packages/nuxt3/src/core/nuxt.ts index 09e6ffb0e80..9dd5196aec7 100644 --- a/packages/nuxt3/src/core/nuxt.ts +++ b/packages/nuxt3/src/core/nuxt.ts @@ -61,7 +61,7 @@ async function initNuxt (nuxt: Nuxt) { // Add addComponent({ name: 'clientOnly', - filePath: resolve(nuxt.options.appDir, 'components/client-only.ts') + filePath: resolve(nuxt.options.appDir, 'components/client-only') }) for (const m of modulesToInstall) { From 09d91ba84e5d40346e939f2033a8024bc25aca34 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Thu, 11 Nov 2021 19:15:07 +0800 Subject: [PATCH 5/9] chore: update --- packages/nuxt3/src/app/components/client-only.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt3/src/app/components/client-only.mjs b/packages/nuxt3/src/app/components/client-only.mjs index e5f49b217f8..c810e5ba257 100644 --- a/packages/nuxt3/src/app/components/client-only.mjs +++ b/packages/nuxt3/src/app/components/client-only.mjs @@ -9,7 +9,7 @@ const ClientOnly = defineComponent({ return () => ( show.value ? slots.default?.() - : slots.fallback?.() + : (slots.fallback ?? slots.placeholder)?.() ) } }) From ead5247982fc84e4e99ed721295f5b781017bedb Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 15 Nov 2021 12:04:57 +0100 Subject: [PATCH 6/9] support placeholder attr --- .../nuxt3/src/app/components/client-only.mjs | 17 +++++++---------- playground/app.vue | 4 ++++ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/nuxt3/src/app/components/client-only.mjs b/packages/nuxt3/src/app/components/client-only.mjs index c810e5ba257..2080a297d1e 100644 --- a/packages/nuxt3/src/app/components/client-only.mjs +++ b/packages/nuxt3/src/app/components/client-only.mjs @@ -1,17 +1,14 @@ import { ref, onMounted, defineComponent } from 'vue' -const ClientOnly = defineComponent({ - setup (_, { slots }) { - const show = ref(false) - onMounted(() => { - show.value = true - }) +export default defineComponent({ + name: 'ClientOnly', + setup (_, { slots, attrs }) { + const mounted = ref(false) + onMounted(() => { mounted.value = true }) return () => ( - show.value + mounted.value ? slots.default?.() - : (slots.fallback ?? slots.placeholder)?.() + : (slots.fallback || slots.placeholder)?.() || attrs.fallback || attrs.placeholder ) } }) - -export default ClientOnly diff --git a/playground/app.vue b/playground/app.vue index 998594c933e..dad2ca5728e 100644 --- a/playground/app.vue +++ b/playground/app.vue @@ -4,6 +4,9 @@

{{ hello }},
Nuxt 3!

+ + Hello {{ l() }} + @@ -16,6 +19,7 @@ const greetings = [ '你好' ] const hello = useState('hello', () => greetings[Math.random() * greetings.length | 0]) +const l = () => window.location.pathname