fix(nuxt): eager load island components map (#24584)

This commit is contained in:
Harlan Wilton 2023-12-19 21:07:34 +11:00 committed by GitHub
parent 0d725e8cfc
commit 642d4dc9de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 64 additions and 2 deletions

View File

@ -89,7 +89,7 @@ export const componentsIslandsTemplate: NuxtTemplate<ComponentsTemplateContext>
return [ return [
'import { defineAsyncComponent } from \'vue\'', 'import { defineAsyncComponent } from \'vue\'',
'export const islandComponents = {', 'export const islandComponents = import.meta.client ? {} : {',
islands.map( islands.map(
(c) => { (c) => {
const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']` const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']`

View File

@ -40,7 +40,9 @@ export const appComponentTemplate: NuxtTemplate<TemplateContext> = {
// TODO: Use an alias // TODO: Use an alias
export const rootComponentTemplate: NuxtTemplate<TemplateContext> = { export const rootComponentTemplate: NuxtTemplate<TemplateContext> = {
filename: 'root-component.mjs', filename: 'root-component.mjs',
getContents: ctx => genExport(ctx.app.rootComponent!, ['default']) // TODO: fix upstream in vite - this ensures that vite generates a module graph for islands
// but should not be necessary (and has a warmup performance cost). See https://github.com/nuxt/nuxt/pull/24584.
getContents: ctx => (ctx.nuxt.options.dev ? "import '#build/components.islands.mjs';\n" : '') + genExport(ctx.app.rootComponent!, ['default'])
} }
// TODO: Use an alias // TODO: Use an alias
export const errorComponentTemplate: NuxtTemplate<TemplateContext> = { export const errorComponentTemplate: NuxtTemplate<TemplateContext> = {

View File

@ -0,0 +1,9 @@
<script lang="ts" setup>
const hmrId = ref(0)
</script>
<template>
<pre id="hmr-id">
HMR ID: {{ hmrId }}
</pre>
</template>

View File

@ -0,0 +1,5 @@
<template>
<div>
<NuxtIsland name="HmrComponent" />
</div>
</template>

View File

@ -100,6 +100,52 @@ if (process.env.TEST_ENV !== 'built' && !isWindows) {
true true
) )
}) })
it('should HMR islands', async () => {
const { page, pageErrors, consoleLogs } = await renderPage('/server-component-hmr')
let hmrId = 0
const resolveHmrId = async () => {
const node = await page.$('#hmr-id')
const text = await node?.innerText() || ''
return Number(text?.trim().split(':')[1].trim())
}
const componentPath = join(fixturePath, 'components/islands/HmrComponent.vue')
const triggerHmr = async () => fsp.writeFile(
componentPath,
(await fsp.readFile(componentPath, 'utf8'))
.replace(`ref(${hmrId++})`, `ref(${hmrId})`)
)
// initial state
await expectWithPolling(
resolveHmrId,
0,
)
// first edit
await triggerHmr()
await expectWithPolling(
resolveHmrId,
1,
)
// just in-case
await triggerHmr()
await expectWithPolling(
resolveHmrId,
2,
)
// ensure no errors
const consoleLogErrors = consoleLogs.filter(i => i.type === 'error')
const consoleLogWarnings = consoleLogs.filter(i => i.type === 'warn')
expect(pageErrors).toEqual([])
expect(consoleLogErrors).toEqual([])
expect(consoleLogWarnings).toEqual([])
await page.close()
}, 60_000)
}) })
} else { } else {
describe.skip('hmr', () => {}) describe.skip('hmr', () => {})