fix(nuxt): move directives to client component island wrapper (#26387)

This commit is contained in:
Julien Huang 2024-03-26 14:47:40 +01:00 committed by GitHub
parent 89a525e917
commit 67c664656c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 4 deletions

View File

@ -108,13 +108,20 @@ export const islandsTransform = createUnplugin((options: ServerOnlyComponentTran
s.appendRight(startingIndex + loc[1].end, '</NuxtTeleportSsrSlot>')
} else if (options.selectiveClient && ('nuxt-client' in node.attributes || ':nuxt-client' in node.attributes)) {
hasNuxtClient = true
const attributeValue = node.attributes[':nuxt-client'] || node.attributes['nuxt-client'] || 'true'
const { loc, attributes } = node
const attributeValue = attributes[':nuxt-client'] || attributes['nuxt-client'] || 'true'
if (isVite) {
// handle granular interactivity
const htmlCode = code.slice(startingIndex + node.loc[0].start, startingIndex + node.loc[1].end)
const uid = hash(id + node.loc[0].start + node.loc[0].end)
const wrapperAttributes = extractAttributes(attributes, ['v-if', 'v-else-if', 'v-else'])
s.overwrite(startingIndex + node.loc[0].start, startingIndex + node.loc[1].end, `<NuxtTeleportIslandComponent to="${node.name}-${uid}" ${rootDir && isDev ? `root-dir="${rootDir}"` : ''} :nuxt-client="${attributeValue}">${htmlCode.replaceAll(NUXTCLIENT_ATTR_RE, '')}</NuxtTeleportIslandComponent>`)
let startTag = code.slice(startingIndex + loc[0].start, startingIndex + loc[0].end).replace(NUXTCLIENT_ATTR_RE, '')
if (wrapperAttributes) {
startTag = startTag.replaceAll(EXTRACTED_ATTRS_RE, '')
}
s.appendLeft(startingIndex + loc[0].start, `<NuxtTeleportIslandComponent${attributeToString(wrapperAttributes)} to="${node.name}-${uid}" ${rootDir && isDev ? `root-dir="${rootDir}"` : ''} :nuxt-client="${attributeValue}">`)
s.overwrite(startingIndex + loc[0].start, startingIndex + loc[0].end, startTag)
s.appendRight(startingIndex + loc[1].end, '</NuxtTeleportIslandComponent>')
}
}
}

View File

@ -380,6 +380,31 @@ describe('islandTransform - server and island components', () => {
`)
expect(result).toContain('import NuxtTeleportIslandComponent from \'#app/components/nuxt-teleport-island-component\'')
})
it('should move v-if to the wrapper component', async () => {
const result = await viteTransform(`<template>
<div>
<HelloWorld v-if="false" nuxt-client />
<HelloWorld v-else-if="true" nuxt-client />
<HelloWorld v-else nuxt-client />
</div>
</template>
`, 'hello.server.vue', false, true)
expect(result).toMatchInlineSnapshot(`
"<script setup>
import { vforToArray as __vforToArray } from '#app/components/utils'
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'</script><template>
<div>
<NuxtTeleportIslandComponent v-if="false" to="HelloWorld-D9uaHyzL7X" :nuxt-client="true"><HelloWorld /></NuxtTeleportIslandComponent>
<NuxtTeleportIslandComponent v-else-if="true" to="HelloWorld-o4RZMtArnE" :nuxt-client="true"><HelloWorld /></NuxtTeleportIslandComponent>
<NuxtTeleportIslandComponent v-else to="HelloWorld-m1IbXHdd8O" :nuxt-client="true"><HelloWorld /></NuxtTeleportIslandComponent>
</div>
</template>
"
`)
})
})
describe('webpack', () => {