From 435ac87961e8c1e4444942affbc9f26590c306f4 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 4 Jul 2023 05:21:27 +0100 Subject: [PATCH] perf(nuxt): allow hmr for server components in dev mode (#21916) --- .../nuxt/src/app/components/nuxt-island.ts | 19 +++++++++++++------ packages/nuxt/src/components/module.ts | 18 +++++++++++++++++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/packages/nuxt/src/app/components/nuxt-island.ts b/packages/nuxt/src/app/components/nuxt-island.ts index 6e97aea954..56bacbafb6 100644 --- a/packages/nuxt/src/app/components/nuxt-island.ts +++ b/packages/nuxt/src/app/components/nuxt-island.ts @@ -67,9 +67,9 @@ export default defineComponent({ const cHead = ref>>>({ link: [], style: [] }) useHead(cHead) - async function _fetchComponent () { + async function _fetchComponent (force = false) { const key = `${props.name}_${hashId.value}` - if (nuxtApp.payload.data[key]) { return nuxtApp.payload.data[key] } + if (nuxtApp.payload.data[key] && !force) { return nuxtApp.payload.data[key] } const url = `/__nuxt_island/${key}` if (process.server && process.env.prerender) { @@ -106,10 +106,10 @@ export default defineComponent({ return result } const key = ref(0) - async function fetchComponent () { + async function fetchComponent (force = false) { nuxtApp[pKey] = nuxtApp[pKey] || {} if (!nuxtApp[pKey][uid.value]) { - nuxtApp[pKey][uid.value] = _fetchComponent().finally(() => { + nuxtApp[pKey][uid.value] = _fetchComponent(force).finally(() => { delete nuxtApp[pKey]![uid.value] }) } @@ -127,10 +127,17 @@ export default defineComponent({ setUid() } - if (process.client) { - watch(props, debounce(fetchComponent, 100)) + if (import.meta.hot) { + import.meta.hot.on(`nuxt-server-component:${props.name}`, () => { + fetchComponent(true) + }) } + if (process.client) { + watch(props, debounce(() => fetchComponent(), 100)) + } + + // TODO: allow lazy loading server islands if (process.server || !nuxtApp.isHydrating) { await fetchComponent() } diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index 571552f319..d21bc541c7 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -1,5 +1,5 @@ import { statSync } from 'node:fs' -import { relative, resolve } from 'pathe' +import { normalize, relative, resolve } from 'pathe' import { addPluginTemplate, addTemplate, addVitePlugin, addWebpackPlugin, defineNuxtModule, resolveAlias, updateTemplates } from '@nuxt/kit' import type { Component, ComponentsDir, ComponentsOptions } from 'nuxt/schema' @@ -227,6 +227,22 @@ export default defineNuxtModule({ getComponents })) } + if (!isServer && nuxt.options.experimental.componentIslands) { + config.plugins.push({ + name: 'nuxt-server-component-hmr', + handleHotUpdate (ctx) { + const components = getComponents() + const filePath = normalize(ctx.file) + const comp = components.find(c => c.filePath === filePath) + if (comp?.mode === 'server') { + ctx.server.ws.send({ + event: `nuxt-server-component:${comp.pascalName}`, + type: 'custom' + }) + } + } + }) + } }) nuxt.hook('webpack:config', (configs) => { configs.forEach((config) => {