refactor(nuxt): rename to data-island-component (#25232)

This commit is contained in:
Daniel Roe 2024-01-16 16:33:45 +00:00 committed by GitHub
parent 18d279336d
commit 430e207bc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 56 additions and 56 deletions

View File

@ -126,7 +126,7 @@ export default defineComponent({
if (import.meta.client && !canLoadClientComponent.value) {
for (const [key, value] of Object.entries(payloadComponents || {})) {
html = html.replace(new RegExp(` data-island-uid="${uid.value}" data-island-client="${key}"[^>]*>`), (full) => {
html = html.replace(new RegExp(` data-island-uid="${uid.value}" data-island-component="${key}"[^>]*>`), (full) => {
return full + value.html
})
}
@ -267,7 +267,7 @@ export default defineComponent({
const { props } = info
const component = components!.get(id)!
// use different selectors for even and odd teleportKey to force trigger the teleport
const vnode = createVNode(Teleport, { to: `${isKeyOdd ? 'div' : ''}[data-island-uid='${uid.value}'][data-island-client="${id}"]` }, {
const vnode = createVNode(Teleport, { to: `${isKeyOdd ? 'div' : ''}[data-island-uid='${uid.value}'][data-island-component="${id}"]` }, {
default: () => {
return [h(component, props)]
}

View File

@ -14,7 +14,7 @@ type ExtendedComponent = Component & {
* this teleport the component in SSR only if it needs to be hydrated on client
*/
export default defineComponent({
name: 'NuxtTeleportIslandClient',
name: 'NuxtTeleportIslandComponent',
props: {
to: {
type: String,
@ -53,7 +53,7 @@ export default defineComponent({
return [h('div', {
style: 'display: contents;',
'data-island-uid': '',
'data-island-client': props.to
'data-island-component': props.to
}, []), h(Teleport, { to: props.to }, slot)]
}
}

View File

@ -13,7 +13,7 @@ import { isVue } from '../core/utils'
interface ServerOnlyComponentTransformPluginOptions {
getComponents: () => Component[]
/**
* passed down to `NuxtTeleportIslandClient`
* passed down to `NuxtTeleportIslandComponent`
* should be done only in dev mode as we use build:manifest result in production
*/
rootDir?: string
@ -33,7 +33,7 @@ const SCRIPT_RE = /<script[^>]*>/g
const HAS_SLOT_OR_CLIENT_RE = /(<slot[^>]*>)|(nuxt-client)/
const TEMPLATE_RE = /<template>([\s\S]*)<\/template>/
const NUXTCLIENT_ATTR_RE = /\snuxt-client(="[^"]*")?/g
const IMPORT_CODE = '\nimport { vforToArray as __vforToArray } from \'#app/components/utils\'' + '\nimport NuxtTeleportIslandClient from \'#app/components/nuxt-teleport-island-client\'' + '\nimport NuxtTeleportSsrSlot from \'#app/components/nuxt-teleport-island-slot\''
const IMPORT_CODE = '\nimport { vforToArray as __vforToArray } from \'#app/components/utils\'' + '\nimport NuxtTeleportIslandComponent from \'#app/components/nuxt-teleport-island-component\'' + '\nimport NuxtTeleportSsrSlot from \'#app/components/nuxt-teleport-island-slot\''
function wrapWithVForDiv (code: string, vfor: string): string {
return `<div v-for="${vfor}" style="display: contents;">${code}</div>`
@ -110,7 +110,7 @@ export const islandsTransform = createUnplugin((options: ServerOnlyComponentTran
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)
s.overwrite(startingIndex + node.loc[0].start, startingIndex + node.loc[1].end, `<NuxtTeleportIslandClient to="${node.name}-${uid}" ${rootDir && isDev ? `root-dir="${rootDir}"` : ''} :nuxt-client="${attributeValue}">${htmlCode.replaceAll(NUXTCLIENT_ATTR_RE, '')}</NuxtTeleportIslandClient>`)
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>`)
}
}
}

View File

@ -635,7 +635,7 @@ function replaceIslandTeleports (ssrContext: NuxtSSRContext, html: string) {
if (matchClientComp) {
const [, uid, clientId] = matchClientComp
if (!uid || !clientId) { continue }
html = html.replace(new RegExp(` data-island-client="${clientId}"[^>]*>`), (full) => {
html = html.replace(new RegExp(` data-island-component="${clientId}"[^>]*>`), (full) => {
return full + teleports[key]
})
continue

View File

@ -74,7 +74,7 @@ describe('islandTransform - server and island components', () => {
</template>
<script setup lang="ts">
import { vforToArray as __vforToArray } from '#app/components/utils'
import NuxtTeleportIslandClient from '#app/components/nuxt-teleport-island-client'
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
const someData = 'some data'
@ -106,7 +106,7 @@ describe('islandTransform - server and island components', () => {
</template>
<script setup lang="ts">
import { vforToArray as __vforToArray } from '#app/components/utils'
import NuxtTeleportIslandClient from '#app/components/nuxt-teleport-island-client'
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
const someData = 'some data'
@ -171,7 +171,7 @@ describe('islandTransform - server and island components', () => {
<script setup lang="ts">
import { vforToArray as __vforToArray } from '#app/components/utils'
import NuxtTeleportIslandClient from '#app/components/nuxt-teleport-island-client'
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
export interface Props {
count?: number;
@ -190,9 +190,9 @@ describe('islandTransform - server and island components', () => {
it('test transform with vite in dev', async () => {
const result = await viteTransform(`<template>
<div>
<!-- should not be wrapped by NuxtTeleportIslandClient -->
<!-- should not be wrapped by NuxtTeleportIslandComponent -->
<HelloWorld />
<!-- should be wrapped by NuxtTeleportIslandClient with a rootDir attr -->
<!-- should be wrapped by NuxtTeleportIslandComponent with a rootDir attr -->
<HelloWorld nuxt-client />
</div>
</template>
@ -205,16 +205,16 @@ describe('islandTransform - server and island components', () => {
expect(normalizeLineEndings(result)).toMatchInlineSnapshot(`
"<template>
<div>
<!-- should not be wrapped by NuxtTeleportIslandClient -->
<!-- should not be wrapped by NuxtTeleportIslandComponent -->
<HelloWorld />
<!-- should be wrapped by NuxtTeleportIslandClient with a rootDir attr -->
<NuxtTeleportIslandClient to="HelloWorld-u9V1gHwUZN" root-dir="/root" :nuxt-client="true"><HelloWorld /></NuxtTeleportIslandClient>
<!-- should be wrapped by NuxtTeleportIslandComponent with a rootDir attr -->
<NuxtTeleportIslandComponent to="HelloWorld-ZsRS8qEyqK" root-dir="/root" :nuxt-client="true"><HelloWorld /></NuxtTeleportIslandComponent>
</div>
</template>
<script setup lang="ts">
import { vforToArray as __vforToArray } from '#app/components/utils'
import NuxtTeleportIslandClient from '#app/components/nuxt-teleport-island-client'
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
import HelloWorld from './HelloWorld.vue'
</script>
@ -241,13 +241,13 @@ describe('islandTransform - server and island components', () => {
"<template>
<div>
<HelloWorld />
<NuxtTeleportIslandClient to="HelloWorld-CyH3UXLuYA" :nuxt-client="true"><HelloWorld /></NuxtTeleportIslandClient>
<NuxtTeleportIslandComponent to="HelloWorld-CyH3UXLuYA" :nuxt-client="true"><HelloWorld /></NuxtTeleportIslandComponent>
</div>
</template>
<script setup lang="ts">
import { vforToArray as __vforToArray } from '#app/components/utils'
import NuxtTeleportIslandClient from '#app/components/nuxt-teleport-island-client'
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
import HelloWorld from './HelloWorld.vue'
</script>
@ -277,13 +277,13 @@ describe('islandTransform - server and island components', () => {
"<template>
<div>
<HelloWorld />
<NuxtTeleportIslandClient to="HelloWorld-eo0XycWCUV" :nuxt-client="nuxtClient"><HelloWorld :nuxt-client="nuxtClient" /></NuxtTeleportIslandClient>
<NuxtTeleportIslandComponent to="HelloWorld-eo0XycWCUV" :nuxt-client="nuxtClient"><HelloWorld :nuxt-client="nuxtClient" /></NuxtTeleportIslandComponent>
</div>
</template>
<script setup lang="ts">
import { vforToArray as __vforToArray } from '#app/components/utils'
import NuxtTeleportIslandClient from '#app/components/nuxt-teleport-island-client'
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
import HelloWorld from './HelloWorld.vue'
@ -318,7 +318,7 @@ describe('islandTransform - server and island components', () => {
<script setup lang="ts">
import { vforToArray as __vforToArray } from '#app/components/utils'
import NuxtTeleportIslandClient from '#app/components/nuxt-teleport-island-client'
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
import HelloWorld from './HelloWorld.vue'
@ -341,17 +341,17 @@ describe('islandTransform - server and island components', () => {
expect(result).toMatchInlineSnapshot(`
"<script setup>
import { vforToArray as __vforToArray } from '#app/components/utils'
import NuxtTeleportIslandClient from '#app/components/nuxt-teleport-island-client'
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'</script><template>
<div>
<HelloWorld />
<NuxtTeleportIslandClient to="HelloWorld-CyH3UXLuYA" :nuxt-client="true"><HelloWorld /></NuxtTeleportIslandClient>
<NuxtTeleportIslandComponent to="HelloWorld-CyH3UXLuYA" :nuxt-client="true"><HelloWorld /></NuxtTeleportIslandComponent>
</div>
</template>
"
`)
expect(result).toContain(`import NuxtTeleportIslandClient from '#app/components/nuxt-teleport-island-client'`)
expect(result).toContain(`import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'`)
})
})
@ -360,10 +360,10 @@ describe('islandTransform - server and island components', () => {
const spyOnWarn = vi.spyOn(console, 'warn')
const result = await webpackTransform(`<template>
<div>
<!-- should not be wrapped by NuxtTeleportIslandClient -->
<!-- should not be wrapped by NuxtTeleportIslandComponent -->
<HelloWorld />
<!-- should be not wrapped by NuxtTeleportIslandClient for now -->
<!-- should be not wrapped by NuxtTeleportIslandComponent for now -->
<HelloWorld nuxt-client />
</div>
</template>
@ -377,17 +377,17 @@ describe('islandTransform - server and island components', () => {
expect(normalizeLineEndings(result)).toMatchInlineSnapshot(`
"<template>
<div>
<!-- should not be wrapped by NuxtTeleportIslandClient -->
<!-- should not be wrapped by NuxtTeleportIslandComponent -->
<HelloWorld />
<!-- should be not wrapped by NuxtTeleportIslandClient for now -->
<!-- should be not wrapped by NuxtTeleportIslandComponent for now -->
<HelloWorld nuxt-client />
</div>
</template>
<script setup lang="ts">
import { vforToArray as __vforToArray } from '#app/components/utils'
import NuxtTeleportIslandClient from '#app/components/nuxt-teleport-island-client'
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
import HelloWorld from './HelloWorld.vue'

View File

@ -1558,12 +1558,12 @@ describe('server components/islands', () => {
await page.waitForLoadState('networkidle')
await page.getByText('Go to page without lazy server component').click()
const text = (await page.innerText('pre')).replaceAll(/ data-island-uid="([^"]*)"/g, '').replace(/data-island-client="([^"]*)"/g, (_, content) => `data-island-client="${content.split('-')[0]}"`)
const text = (await page.innerText('pre')).replaceAll(/ data-island-uid="([^"]*)"/g, '').replace(/data-island-component="([^"]*)"/g, (_, content) => `data-island-component="${content.split('-')[0]}"`)
if (isWebpack) {
expect(text).toMatchInlineSnapshot('" End page <pre></pre><section id="fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"></div><!--]--></div></section><section id="no-fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"></div><!--]--></div></section><div> ServerWithClient.server.vue : <p>count: 0</p> This component should not be preloaded <div><!--[--><div>a</div><div>b</div><div>c</div><!--]--></div> This is not interactive <div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><div class="interactive-component-wrapper" style="border:solid 1px red;"> The component bellow is not a slot but declared as interactive <div class="sugar-counter" nuxt-client=""> Sugar Counter 12 x 1 = 12 <button> Inc </button></div></div></div>"')
} else {
expect(text).toMatchInlineSnapshot(`" End page <pre></pre><section id="fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"></div><!--]--></div></section><section id="no-fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"></div><!--]--></div></section><div> ServerWithClient.server.vue : <p>count: 0</p> This component should not be preloaded <div><!--[--><div>a</div><div>b</div><div>c</div><!--]--></div> This is not interactive <div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><div class="interactive-component-wrapper" style="border:solid 1px red;"> The component bellow is not a slot but declared as interactive <!--[--><div style="display: contents;" data-island-client="Counter"></div><!--teleport start--><!--teleport end--><!--]--></div></div>"`)
expect(text).toMatchInlineSnapshot(`" End page <pre></pre><section id="fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"></div><!--]--></div></section><section id="no-fallback"><div> This is a .server (20ms) async component that was very long ... <div id="async-server-component-count">42</div><div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><!--[--><div style="display: contents;" data-island-slot="default"></div><!--]--></div></section><div> ServerWithClient.server.vue : <p>count: 0</p> This component should not be preloaded <div><!--[--><div>a</div><div>b</div><div>c</div><!--]--></div> This is not interactive <div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><div class="interactive-component-wrapper" style="border:solid 1px red;"> The component bellow is not a slot but declared as interactive <!--[--><div style="display: contents;" data-island-component="Counter"></div><!--teleport start--><!--teleport end--><!--]--></div></div>"`)
}
expect(text).toContain('async component that was very long')
@ -1804,7 +1804,7 @@ describe('component islands', () => {
if (isDev()) {
result.head.link = result.head.link.filter(l => !l.href.includes('@nuxt+ui-templates') && (l.href.startsWith('_nuxt/components/islands/') && l.href.includes('_nuxt/components/islands/LongAsyncComponent')))
}
result.html = result.html.replaceAll(/ (data-island-uid|data-island-client)="([^"]*)"/g, '')
result.html = result.html.replaceAll(/ (data-island-uid|data-island-component)="([^"]*)"/g, '')
expect(result).toMatchInlineSnapshot(`
{
"components": {},
@ -1869,7 +1869,7 @@ describe('component islands', () => {
result.props = {}
result.components = {}
result.slots = {}
result.html = result.html.replaceAll(/ (data-island-uid|data-island-client)="([^"]*)"/g, '')
result.html = result.html.replaceAll(/ (data-island-uid|data-island-component)="([^"]*)"/g, '')
expect(result).toMatchInlineSnapshot(`
{
@ -1895,7 +1895,7 @@ describe('component islands', () => {
const { components } = result
result.components = {}
result.slots = {}
result.html = result.html.replace(/ data-island-client="([^"]*)"/g, (_, content) => ` data-island-client="${content.split('-')[0]}"`)
result.html = result.html.replace(/ data-island-component="([^"]*)"/g, (_, content) => ` data-island-component="${content.split('-')[0]}"`)
const teleportsEntries = Object.entries(components || {})
@ -1906,7 +1906,7 @@ describe('component islands', () => {
"link": [],
"style": [],
},
"html": "<div data-island-uid> ServerWithClient.server.vue : <p>count: 0</p> This component should not be preloaded <div><!--[--><div>a</div><div>b</div><div>c</div><!--]--></div> This is not interactive <div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><div class="interactive-component-wrapper" style="border:solid 1px red;"> The component bellow is not a slot but declared as interactive <!--[--><div style="display: contents;" data-island-uid data-island-client="Counter"></div><!--teleport start--><!--teleport end--><!--]--></div></div>",
"html": "<div data-island-uid> ServerWithClient.server.vue : <p>count: 0</p> This component should not be preloaded <div><!--[--><div>a</div><div>b</div><div>c</div><!--]--></div> This is not interactive <div class="sugar-counter"> Sugar Counter 12 x 1 = 12 <button> Inc </button></div><div class="interactive-component-wrapper" style="border:solid 1px red;"> The component bellow is not a slot but declared as interactive <!--[--><div style="display: contents;" data-island-uid data-island-component="Counter"></div><!--teleport start--><!--teleport end--><!--]--></div></div>",
"slots": {},
"state": {},
}