From 832b1e6372cd3a5c1f17a4fa13a22ec775886e48 Mon Sep 17 00:00:00 2001 From: julien huang Date: Thu, 30 Mar 2023 21:49:01 +0200 Subject: [PATCH 01/63] fix(nuxt): fix cross-request nuxt app pollution with nuxt islands --- packages/nuxt/src/core/runtime/nitro/renderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index 19439bb7fa3f..cee04fad95df 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -148,7 +148,7 @@ async function getIslandContext (event: H3Event): Promise { const context = event.node.req.method === 'GET' ? getQuery(event) : await readBody(event) const ctx: NuxtIslandContext = { - url: '/', + url: event.node.req.url, ...context, id: hashId, name: componentName, From 857781e557131a514695c2a0c2524fc97b266217 Mon Sep 17 00:00:00 2001 From: julien huang Date: Thu, 30 Mar 2023 21:49:01 +0200 Subject: [PATCH 02/63] Revert "fix(nuxt): fix cross-request nuxt app pollution with nuxt islands" This reverts commit 49a0f5195468695142763006fb9d62e030eae07b. --- packages/nuxt/src/core/runtime/nitro/renderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index cee04fad95df..19439bb7fa3f 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -148,7 +148,7 @@ async function getIslandContext (event: H3Event): Promise { const context = event.node.req.method === 'GET' ? getQuery(event) : await readBody(event) const ctx: NuxtIslandContext = { - url: event.node.req.url, + url: '/', ...context, id: hashId, name: componentName, From 7f061eca9202c9ca1e9bca48ceb1021ae3bd08fc Mon Sep 17 00:00:00 2001 From: julien huang Date: Thu, 30 Mar 2023 21:49:01 +0200 Subject: [PATCH 03/63] feat: working nuxtisland slot --- .../src/app/components/island-renderer.ts | 24 +++++- .../nuxt/src/app/components/nuxt-island.ts | 75 ++++++++++++++++++- .../AsyncServerComponent.server.vue | 1 + .../components/islands/LongAsyncComponent.vue | 1 + test/fixtures/basic/pages/islands.vue | 24 ++++-- 5 files changed, 111 insertions(+), 14 deletions(-) diff --git a/packages/nuxt/src/app/components/island-renderer.ts b/packages/nuxt/src/app/components/island-renderer.ts index 35ab352f8ef5..d284da53f53d 100644 --- a/packages/nuxt/src/app/components/island-renderer.ts +++ b/packages/nuxt/src/app/components/island-renderer.ts @@ -1,9 +1,12 @@ +import { randomUUID } from 'node:crypto' import type { defineAsyncComponent } from 'vue' -import { defineComponent, createVNode } from 'vue' +import { renderSlot, createBlock, defineComponent, createVNode, h } from 'vue' // @ts-ignore +import { ssrRenderSlot } from 'vue/server-renderer' import * as islandComponents from '#build/components.islands.mjs' import { createError } from '#app/composables/error' +const SLOT_RENDER_RE = /ssrRenderSlot\(_ctx.\$slots, "([a-zA-Z]*)"/g export default defineComponent({ props: { @@ -12,15 +15,30 @@ export default defineComponent({ required: true } }, - setup (props) { + async setup (props, ctx) { + const uid = randomUUID() const component = islandComponents[props.context.name] as ReturnType + const slots: Record = {} + if (typeof component === 'object') { + await (component.__asyncLoader as Function)?.() + const matched = [...(component.__asyncResolved.ssrRender as Function).toString().matchAll(SLOT_RENDER_RE)] + for (const [_full, slotName] of matched) { + slots[slotName] = () => { + return createVNode('div', { 'v-ssr-slot-name': slotName }, + renderSlot(ctx.slots, slotName) + ) + } + } + } if (!component) { throw createError({ statusCode: 404, statusMessage: `Island component not found: ${JSON.stringify(component)}` }) } - return () => createVNode(component || 'span', props.context.props) + + const toRender = component.__asyncResolved ?? component + return () => [createVNode(toRender || 'span', { ...props.context.props, 'v-ssr-component-uid': uid }, slots)] } }) diff --git a/packages/nuxt/src/app/components/nuxt-island.ts b/packages/nuxt/src/app/components/nuxt-island.ts index 60a2c8e23d5c..41f9a88bf78d 100644 --- a/packages/nuxt/src/app/components/nuxt-island.ts +++ b/packages/nuxt/src/app/components/nuxt-island.ts @@ -1,4 +1,4 @@ -import { defineComponent, createStaticVNode, computed, ref, watch, getCurrentInstance } from 'vue' +import { defineComponent, createStaticVNode, computed, ref, watch, getCurrentInstance, createBlock, Teleport, onMounted, createVNode } from 'vue' import { debounce } from 'perfect-debounce' import { hash } from 'ohash' import { appendHeader } from 'h3' @@ -10,6 +10,7 @@ import { useNuxtApp } from '#app/nuxt' import { useRequestEvent } from '#app/composables/ssr' const pKey = '_islandPromises' +const SSR_UID_RE = /v-ssr-component-uid="([^"]*)"/ export default defineComponent({ name: 'NuxtIsland', @@ -27,13 +28,19 @@ export default defineComponent({ default: () => ({}) } }, - async setup (props) { + async setup (props, { slots }) { const nuxtApp = useNuxtApp() const hashId = computed(() => hash([props.name, props.props, props.context])) const instance = getCurrentInstance()! const event = useRequestEvent() - + const mounted = ref(false) + onMounted(() => { mounted.value = true }) + console.log(instance.vnode.el) const html = ref(process.client ? instance.vnode.el?.outerHTML ?? '
' : '
') + let uid = html.value.match(SSR_UID_RE)?.[1] + function setUid () { + uid = html.value.match(SSR_UID_RE)?.[1] + } const cHead = ref>>>({ link: [], style: [] }) useHead(cHead) @@ -63,6 +70,7 @@ export default defineComponent({ cHead.value.link = res.head.link cHead.value.style = res.head.style html.value = res.html + setUid() } if (process.client) { @@ -72,7 +80,66 @@ export default defineComponent({ if (process.server || !nuxtApp.isHydrating) { await fetchComponent() } + if (process.client) { + console.log(html.value) + } - return () => createStaticVNode(html.value, 1) + return (ctx) => { + if (process.server) { + return [createStaticVNode(html.value, 1)] + } + if (!mounted.value && process.client) { + html.value = getFragmentHTML(instance.vnode.el).join('') + setUid() + return [getStaticVNode(instance.vnode)] + } + const nodes = [createStaticVNode(html.value, 1)] + console.log(uid) + if (uid) { + for (const slot in slots) { + nodes.push(createVNode(Teleport, { to: `[v-ssr-component-uid='${uid}'] [v-ssr-slot-name='${slot}']` }, [slots[slot]?.()])) + } + } + return nodes + } } }) +function getStaticVNode (vnode) { + const fragment = getFragmentHTML(vnode.el) + + if (fragment.length === 0) { + return null + } + return createStaticVNode(fragment.join(''), fragment.length) +} + +function getFragmentHTML (element) { + if (element) { + if (element.nodeName === '#comment' && element.nodeValue === '[') { + return getFragmentChildren(element) + } + return [element.outerHTML] + } + return [] +} + +function getFragmentChildren (element, blocks = []) { + if (element && element.nodeName) { + if (isEndFragment(element)) { + return blocks + } else if (!isStartFragment(element)) { + blocks.push(element.outerHTML) + } + + getFragmentChildren(element.nextSibling, blocks) + } + return blocks +} + +function isStartFragment (element) { + return element.nodeName === '#comment' && element.nodeValue === '[' +} + +function isEndFragment (element) { + return element.nodeName === '#comment' && element.nodeValue === ']' +} diff --git a/test/fixtures/basic/components/AsyncServerComponent.server.vue b/test/fixtures/basic/components/AsyncServerComponent.server.vue index 6bbee5b9ab58..4bd9a1d4b05a 100644 --- a/test/fixtures/basic/components/AsyncServerComponent.server.vue +++ b/test/fixtures/basic/components/AsyncServerComponent.server.vue @@ -5,6 +5,7 @@
{{ count }}
+ diff --git a/test/fixtures/basic/components/islands/LongAsyncComponent.vue b/test/fixtures/basic/components/islands/LongAsyncComponent.vue index b5e9c0e9858d..117c3b38fc04 100644 --- a/test/fixtures/basic/components/islands/LongAsyncComponent.vue +++ b/test/fixtures/basic/components/islands/LongAsyncComponent.vue @@ -4,6 +4,7 @@
{{ count }}
+

hello world !!!

diff --git a/test/fixtures/basic/pages/islands.vue b/test/fixtures/basic/pages/islands.vue index 6ea3d6d5d7c3..f3f913bf2e9a 100644 --- a/test/fixtures/basic/pages/islands.vue +++ b/test/fixtures/basic/pages/islands.vue @@ -7,7 +7,7 @@ const islandProps = ref({ }) const routeIslandVisible = ref(false) - +const testCount = ref(0) const count = ref(0) @@ -31,13 +31,23 @@ const count = ref(0)

async .server component

- + + +
WONDERFUl TEST SLOT .server
- Async island component (20ms): - - + Async component (1000ms): +
+ +
SLOT TESTING THIS IS A NICE DEFAULT SLOT
+ + +
+ +
From bfa2a90644934ee5e5a6f431fa2834d6ee03650b Mon Sep 17 00:00:00 2001 From: julien huang Date: Thu, 30 Mar 2023 21:49:01 +0200 Subject: [PATCH 04/63] style: lint --- .../nuxt/src/app/components/island-renderer.ts | 6 ++---- packages/nuxt/src/app/components/nuxt-island.ts | 17 ++++++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/nuxt/src/app/components/island-renderer.ts b/packages/nuxt/src/app/components/island-renderer.ts index d284da53f53d..b62e01278a05 100644 --- a/packages/nuxt/src/app/components/island-renderer.ts +++ b/packages/nuxt/src/app/components/island-renderer.ts @@ -1,9 +1,8 @@ import { randomUUID } from 'node:crypto' import type { defineAsyncComponent } from 'vue' -import { renderSlot, createBlock, defineComponent, createVNode, h } from 'vue' +import { renderSlot, createVNode, defineComponent } from 'vue' // @ts-ignore -import { ssrRenderSlot } from 'vue/server-renderer' import * as islandComponents from '#build/components.islands.mjs' import { createError } from '#app/composables/error' const SLOT_RENDER_RE = /ssrRenderSlot\(_ctx.\$slots, "([a-zA-Z]*)"/g @@ -38,7 +37,6 @@ export default defineComponent({ }) } - const toRender = component.__asyncResolved ?? component - return () => [createVNode(toRender || 'span', { ...props.context.props, 'v-ssr-component-uid': uid }, slots)] + return () => [createVNode(component || 'span', { ...props.context.props, 'v-ssr-component-uid': uid }, slots)] } }) diff --git a/packages/nuxt/src/app/components/nuxt-island.ts b/packages/nuxt/src/app/components/nuxt-island.ts index 41f9a88bf78d..c3c5bbf713cb 100644 --- a/packages/nuxt/src/app/components/nuxt-island.ts +++ b/packages/nuxt/src/app/components/nuxt-island.ts @@ -1,4 +1,5 @@ -import { defineComponent, createStaticVNode, computed, ref, watch, getCurrentInstance, createBlock, Teleport, onMounted, createVNode } from 'vue' +import type { VNode, RendererNode } from 'vue' +import { defineComponent, createStaticVNode, computed, ref, watch, getCurrentInstance, Teleport, onMounted, createVNode } from 'vue' import { debounce } from 'perfect-debounce' import { hash } from 'ohash' import { appendHeader } from 'h3' @@ -84,7 +85,7 @@ export default defineComponent({ console.log(html.value) } - return (ctx) => { + return () => { if (process.server) { return [createStaticVNode(html.value, 1)] } @@ -104,7 +105,9 @@ export default defineComponent({ } } }) -function getStaticVNode (vnode) { + +// TODO refactor with https://github.com/nuxt/nuxt/pull/19231 +function getStaticVNode (vnode: VNode) { const fragment = getFragmentHTML(vnode.el) if (fragment.length === 0) { @@ -113,7 +116,7 @@ function getStaticVNode (vnode) { return createStaticVNode(fragment.join(''), fragment.length) } -function getFragmentHTML (element) { +function getFragmentHTML (element: RendererNode | null) { if (element) { if (element.nodeName === '#comment' && element.nodeValue === '[') { return getFragmentChildren(element) @@ -123,7 +126,7 @@ function getFragmentHTML (element) { return [] } -function getFragmentChildren (element, blocks = []) { +function getFragmentChildren (element: RendererNode | null, blocks: string[] = []) { if (element && element.nodeName) { if (isEndFragment(element)) { return blocks @@ -136,10 +139,10 @@ function getFragmentChildren (element, blocks = []) { return blocks } -function isStartFragment (element) { +function isStartFragment (element: RendererNode) { return element.nodeName === '#comment' && element.nodeValue === '[' } -function isEndFragment (element) { +function isEndFragment (element: RendererNode) { return element.nodeName === '#comment' && element.nodeValue === ']' } From b579885a08cb9400b673441650bd3f0c6079496d Mon Sep 17 00:00:00 2001 From: julien huang Date: Thu, 30 Mar 2023 21:49:02 +0200 Subject: [PATCH 05/63] test(fixtures): add default slot --- test/fixtures/basic/components/islands/LongAsyncComponent.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/test/fixtures/basic/components/islands/LongAsyncComponent.vue b/test/fixtures/basic/components/islands/LongAsyncComponent.vue index 117c3b38fc04..f363e228d61a 100644 --- a/test/fixtures/basic/components/islands/LongAsyncComponent.vue +++ b/test/fixtures/basic/components/islands/LongAsyncComponent.vue @@ -1,5 +1,6 @@ From 9fb431be4039b4d0f959fd8a9c7eb92c47bf7d70 Mon Sep 17 00:00:00 2001 From: julien huang Date: Thu, 30 Mar 2023 21:57:11 +0200 Subject: [PATCH 19/63] chore: lint and remove logs --- packages/nuxt/src/app/components/island-renderer.ts | 2 +- packages/nuxt/src/components/runtime/server-component.ts | 2 +- test/fixtures/basic/components/AsyncServerComponent.server.vue | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nuxt/src/app/components/island-renderer.ts b/packages/nuxt/src/app/components/island-renderer.ts index b2ad7193b850..1a9b678bdb08 100644 --- a/packages/nuxt/src/app/components/island-renderer.ts +++ b/packages/nuxt/src/app/components/island-renderer.ts @@ -24,7 +24,7 @@ export default defineComponent({ } } } - console.log(uid, props.context.slotsName) + if (!component) { throw createError({ statusCode: 404, diff --git a/packages/nuxt/src/components/runtime/server-component.ts b/packages/nuxt/src/components/runtime/server-component.ts index 137316a5e150..36b60a986908 100644 --- a/packages/nuxt/src/components/runtime/server-component.ts +++ b/packages/nuxt/src/components/runtime/server-component.ts @@ -1,4 +1,4 @@ -import { defineComponent, h } from 'vue' +import { defineComponent, h } from 'vue' import NuxtIsland from '#app/components/nuxt-island' export const createServerComponent = (name: string) => { diff --git a/test/fixtures/basic/components/AsyncServerComponent.server.vue b/test/fixtures/basic/components/AsyncServerComponent.server.vue index 4bd9a1d4b05a..221224efc45e 100644 --- a/test/fixtures/basic/components/AsyncServerComponent.server.vue +++ b/test/fixtures/basic/components/AsyncServerComponent.server.vue @@ -5,7 +5,7 @@
{{ count }}
- + From f99cdf751df7f4244bd0e4277f38906455fc40b5 Mon Sep 17 00:00:00 2001 From: julien huang Date: Thu, 30 Mar 2023 22:14:54 +0200 Subject: [PATCH 20/63] feat(server-component): pass slot to NuxtIsland --- packages/nuxt/src/components/runtime/server-component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nuxt/src/components/runtime/server-component.ts b/packages/nuxt/src/components/runtime/server-component.ts index 36b60a986908..4dcfa8cce502 100644 --- a/packages/nuxt/src/components/runtime/server-component.ts +++ b/packages/nuxt/src/components/runtime/server-component.ts @@ -5,11 +5,11 @@ export const createServerComponent = (name: string) => { return defineComponent({ name, inheritAttrs: false, - setup (_props, { attrs }) { + setup (_props, { attrs, slots }) { return () => h(NuxtIsland, { name, props: attrs - }) + }, slots) } }) } From b28f5c42ac46df15ab0372e0a6c23b4cd1e43469 Mon Sep 17 00:00:00 2001 From: julien huang Date: Fri, 31 Mar 2023 00:04:11 +0200 Subject: [PATCH 21/63] chore: remove useless fragment --- packages/nuxt/src/app/components/island-renderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/app/components/island-renderer.ts b/packages/nuxt/src/app/components/island-renderer.ts index 1a9b678bdb08..447445c2b90e 100644 --- a/packages/nuxt/src/app/components/island-renderer.ts +++ b/packages/nuxt/src/app/components/island-renderer.ts @@ -32,6 +32,6 @@ export default defineComponent({ }) } - return () => [createVNode(component || 'span', { ...props.context.props, 'v-ssr-component-uid': uid }, slots)] + return () => createVNode(component || 'span', { ...props.context.props, 'v-ssr-component-uid': uid }, slots) } }) From c2e3af3d45af1aaaff567e86a29b3b6dbc8a4593 Mon Sep 17 00:00:00 2001 From: julien huang Date: Fri, 31 Mar 2023 00:05:01 +0200 Subject: [PATCH 22/63] test: update test --- test/basic.test.ts | 14 +++++++++----- test/fixtures/basic/pages/islands.vue | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/test/basic.test.ts b/test/basic.test.ts index e99c31a01733..f1a6ede1b491 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -75,7 +75,7 @@ describe('pages', () => { // should apply attributes to client-only components expect(html).toContain('
') // should render server-only components - expect(html).toContain('
server-only component
') + expect(html.replace(/ v-ssr-component-uid="([^"]*)"/g, '')).toContain('
server-only component
') // should register global components automatically expect(html).toContain('global component registered automatically') expect(html).toContain('global component via suffix') @@ -1082,6 +1082,7 @@ describe('app config', () => { describe('component islands', () => { it('renders components with route', async () => { const result: NuxtIslandResponse = await $fetch('/__nuxt_island/RouteComponent?url=/foo') + result.html = result.html.replace(/ v-ssr-component-uid="([^"]*)"/g, '') 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/RouteComponent'))) @@ -1109,13 +1110,14 @@ 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.replace(/ v-ssr-component-uid="([^"]*)"/g, '') expect(result).toMatchInlineSnapshot(` { "head": { "link": [], "style": [], }, - "html": "
that was very long ...
3

hello world !!!

", + "html": "
count is above 2
that was very long ...
3

hello world !!!

", "state": {}, } `) @@ -1130,13 +1132,14 @@ 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/AsyncServerComponent'))) } + result.html = result.html.replace(/ v-ssr-component-uid="([^"]*)"/g, '') expect(result).toMatchInlineSnapshot(` { "head": { "link": [], "style": [], }, - "html": "
This is a .server (20ms) async component that was very long ...
2
", + "html": "
This is a .server (20ms) async component that was very long ...
2
", "state": {}, } `) @@ -1151,6 +1154,7 @@ describe('component islands', () => { obj: { foo: 42, bar: false, me: 'hi' } }) })) + result.html = result.html.replace(/ v-ssr-component-uid="([^"]*)"/g, '') if (isDev()) { result.head.link = result.head.link.filter(l => !l.href.includes('@nuxt+ui-templates')) @@ -1178,7 +1182,7 @@ describe('component islands', () => { }, ], } - `) + `) } else if (isDev() && !isWebpack) { expect(result.head).toMatchInlineSnapshot(` { @@ -1194,7 +1198,7 @@ describe('component islands', () => { `) } - expect(result.html.replace(/data-v-\w+|"|/g, '')).toMatchInlineSnapshot(` + expect(result.html.replace(/data-v-\w+|"|/g, '').replace(/v-ssr-component-uid="([^"]*)"/g, '')).toMatchInlineSnapshot(` "
Was router enabled: true
Props:
{
       number: 3487,
       str: something,
diff --git a/test/fixtures/basic/pages/islands.vue b/test/fixtures/basic/pages/islands.vue
index 3a2bdbaafe9c..083d6b3423fd 100644
--- a/test/fixtures/basic/pages/islands.vue
+++ b/test/fixtures/basic/pages/islands.vue
@@ -19,7 +19,7 @@ const count = ref(0)
       
       
     
-
From 3081c05c6d33ac0e48053b0a7e9e89fe20b23876 Mon Sep 17 00:00:00 2001 From: julien huang Date: Fri, 31 Mar 2023 00:11:34 +0200 Subject: [PATCH 23/63] chore: bump server bundle size --- test/bundle.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bundle.test.ts b/test/bundle.test.ts index e1d60b24ea0b..064dbf51c8b6 100644 --- a/test/bundle.test.ts +++ b/test/bundle.test.ts @@ -40,7 +40,7 @@ describe.skipIf(isWindows)('minimal nuxt application', () => { it('default server bundle size', async () => { stats.server = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir) - expect(stats.server.totalBytes).toBeLessThan(93200) + expect(stats.server.totalBytes).toBeLessThan(94300) const modules = await analyzeSizes('node_modules/**/*', serverDir) expect(modules.totalBytes).toBeLessThan(2694900) From 334edf33b3ed9f823cfc196848b8bf071cfee7c1 Mon Sep 17 00:00:00 2001 From: julien huang Date: Fri, 31 Mar 2023 00:23:18 +0200 Subject: [PATCH 24/63] test: udpate test --- test/basic.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/basic.test.ts b/test/basic.test.ts index f1a6ede1b491..8fc3f749d745 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -1117,7 +1117,7 @@ describe('component islands', () => { "link": [], "style": [], }, - "html": "
count is above 2
that was very long ...
3

hello world !!!

", + "html": "
count is above 2
that was very long ...
3

hello world !!!

", "state": {}, } `) From 089a54560c53f661e57e65f0d2eaba0f58ea4f28 Mon Sep 17 00:00:00 2001 From: julien huang Date: Fri, 31 Mar 2023 00:51:49 +0200 Subject: [PATCH 25/63] docs(server): update alert block --- docs/2.guide/2.directory-structure/1.components.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/2.guide/2.directory-structure/1.components.md b/docs/2.guide/2.directory-structure/1.components.md index 7a39da99f66f..7765bc54a4a2 100644 --- a/docs/2.guide/2.directory-structure/1.components.md +++ b/docs/2.guide/2.directory-structure/1.components.md @@ -296,8 +296,8 @@ Now you can register server-only components with the `.server` suffix and use th ``` -::alert{type=warning} -Slots are not supported by server components in their current state of development. +::alert{type=info} +Slots can be interactive and are wrapped within a `
` with `display: contents;` :: ### Paired with a `.client` component From 07773cd7b689c573382deece24de506d432295bc Mon Sep 17 00:00:00 2001 From: julien huang Date: Sun, 2 Apr 2023 21:37:40 +0200 Subject: [PATCH 26/63] docs(server-components): update limitations --- docs/2.guide/2.directory-structure/1.components.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/2.guide/2.directory-structure/1.components.md b/docs/2.guide/2.directory-structure/1.components.md index 7765bc54a4a2..713131bfb8ac 100644 --- a/docs/2.guide/2.directory-structure/1.components.md +++ b/docs/2.guide/2.directory-structure/1.components.md @@ -300,6 +300,11 @@ Now you can register server-only components with the `.server` suffix and use th Slots can be interactive and are wrapped within a `
` with `display: contents;` :: +::alert{type=warning} +Scoped slots are not supported by server components in their current state of development. +Server only components slots can't be conditionnal and must be called when rendering the component. +:: + ### Paired with a `.client` component In this case, the `.server` + `.client` components are two 'halves' of a component and can be used in advanced use cases for separate implementations of a component on server and client side. From be40a575155bbc531055a34a64a79ca229838cb8 Mon Sep 17 00:00:00 2001 From: julien huang Date: Mon, 3 Apr 2023 20:28:11 +0200 Subject: [PATCH 27/63] chore(test): bump server bundle size --- test/bundle.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bundle.test.ts b/test/bundle.test.ts index 064dbf51c8b6..b25950a99475 100644 --- a/test/bundle.test.ts +++ b/test/bundle.test.ts @@ -40,7 +40,7 @@ describe.skipIf(isWindows)('minimal nuxt application', () => { it('default server bundle size', async () => { stats.server = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir) - expect(stats.server.totalBytes).toBeLessThan(94300) + expect(stats.server.totalBytes).toBeLessThan(94450) const modules = await analyzeSizes('node_modules/**/*', serverDir) expect(modules.totalBytes).toBeLessThan(2694900) From 4a94f324d5458ff34978f327845c4db5f107d22f Mon Sep 17 00:00:00 2001 From: julien huang Date: Mon, 3 Apr 2023 20:35:48 +0200 Subject: [PATCH 28/63] chore: update lock --- pnpm-lock.yaml | 598 ++++++------------------------------------------- 1 file changed, 69 insertions(+), 529 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cd9a0638ae4f..4f50cae6fdc3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -161,7 +161,7 @@ importers: version: link:../../../packages/nuxt vitest: specifier: latest - version: 0.29.7 + version: 0.29.8(playwright@1.32.1) examples/app-config: devDependencies: @@ -410,7 +410,7 @@ importers: version: 2.1.2 unimport: specifier: ^3.0.4 - version: 3.0.4(rollup@3.19.1) + version: 3.0.4(rollup@3.20.2) untyped: specifier: ^1.3.2 version: 1.3.2 @@ -631,7 +631,7 @@ importers: version: 1.2.2 unimport: specifier: ^3.0.4 - version: 3.0.4(rollup@3.19.1) + version: 3.0.4(rollup@3.20.2) unplugin: specifier: ^1.3.1 version: 1.3.1 @@ -698,7 +698,7 @@ importers: version: 1.1.1 unimport: specifier: ^3.0.4 - version: 3.0.4(rollup@3.19.1) + version: 3.0.4(rollup@3.20.2) untyped: specifier: ^1.3.2 version: 1.3.2 @@ -1082,6 +1082,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/highlight': 7.18.6 + dev: false /@babel/code-frame@7.21.4: resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} @@ -1136,7 +1137,6 @@ packages: semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: false /@babel/generator@7.21.4: resolution: {integrity: sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==} @@ -1151,7 +1151,7 @@ packages: resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/helper-compilation-targets@7.21.4(@babel/core@7.21.3): resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} @@ -1178,7 +1178,6 @@ packages: browserslist: 4.21.5 lru-cache: 5.1.1 semver: 6.3.0 - dev: false /@babel/helper-create-class-features-plugin@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==} @@ -1207,7 +1206,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.20.7 - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/helper-hoist-variables@7.18.6: resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} @@ -1219,7 +1218,7 @@ packages: resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/helper-module-imports@7.18.6: resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} @@ -1246,7 +1245,7 @@ packages: resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/helper-plugin-utils@7.20.2: resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} @@ -1260,8 +1259,8 @@ packages: '@babel/helper-member-expression-to-functions': 7.21.0 '@babel/helper-optimise-call-expression': 7.18.6 '@babel/template': 7.20.7 - '@babel/traverse': 7.21.3 - '@babel/types': 7.21.3 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color @@ -1275,13 +1274,13 @@ packages: resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/helper-split-export-declaration@7.18.6: resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/helper-string-parser@7.19.4: resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} @@ -1313,13 +1312,6 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/parser@7.21.3: - resolution: {integrity: sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.21.3 - /@babel/parser@7.21.4: resolution: {integrity: sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==} engines: {node: '>=6.0.0'} @@ -1370,23 +1362,6 @@ packages: '@babel/parser': 7.21.4 '@babel/types': 7.21.4 - /@babel/traverse@7.21.3: - resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.21.4 - '@babel/generator': 7.21.4 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.21.0 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.21.4 - '@babel/types': 7.21.4 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - /@babel/traverse@7.21.4: resolution: {integrity: sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==} engines: {node: '>=6.9.0'} @@ -1404,14 +1379,6 @@ packages: transitivePeerDependencies: - supports-color - /@babel/types@7.21.3: - resolution: {integrity: sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - /@babel/types@7.21.4: resolution: {integrity: sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==} engines: {node: '>=6.9.0'} @@ -1439,15 +1406,6 @@ packages: jsdoc-type-pratt-parser: 4.0.0 dev: true - /@esbuild/android-arm64@0.17.11: - resolution: {integrity: sha512-QnK4d/zhVTuV4/pRM4HUjcsbl43POALU2zvBynmrrqZt9LPcLA3x1fTZPBg2RRguBQnJcnU059yKr+bydkntjg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm64@0.17.12: resolution: {integrity: sha512-WQ9p5oiXXYJ33F2EkE3r0FRDFVpEdcDiwNX3u7Xaibxfx6vQE0Sb8ytrfQsA5WO6kDn6mDfKLh6KrPBjvkk7xA==} engines: {node: '>=12'} @@ -1456,14 +1414,6 @@ packages: requiresBuild: true optional: true - /@esbuild/android-arm64@0.17.14: - resolution: {integrity: sha512-eLOpPO1RvtsP71afiFTvS7tVFShJBCT0txiv/xjFBo5a7R7Gjw7X0IgIaFoLKhqXYAXhahoXm7qAmRXhY4guJg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - /@esbuild/android-arm64@0.17.15: resolution: {integrity: sha512-0kOB6Y7Br3KDVgHeg8PRcvfLkq+AccreK///B4Z6fNZGr/tNHX0z2VywCc7PTeWp+bPvjA5WMvNXltHw5QjAIA==} engines: {node: '>=12'} @@ -1481,15 +1431,6 @@ packages: dev: true optional: true - /@esbuild/android-arm@0.17.11: - resolution: {integrity: sha512-CdyX6sRVh1NzFCsf5vw3kULwlAhfy9wVt8SZlrhQ7eL2qBjGbFhRBWkkAzuZm9IIEOCKJw4DXA6R85g+qc8RDw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.17.12: resolution: {integrity: sha512-E/sgkvwoIfj4aMAPL2e35VnUJspzVYl7+M1B2cqeubdBhADV4uPon0KCc8p2G+LqSJ6i8ocYPCqY3A4GGq0zkQ==} engines: {node: '>=12'} @@ -1498,14 +1439,6 @@ packages: requiresBuild: true optional: true - /@esbuild/android-arm@0.17.14: - resolution: {integrity: sha512-0CnlwnjDU8cks0yJLXfkaU/uoLyRf9VZJs4p1PskBr2AlAHeEsFEwJEo0of/Z3g+ilw5mpyDwThlxzNEIxOE4g==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - /@esbuild/android-arm@0.17.15: resolution: {integrity: sha512-sRSOVlLawAktpMvDyJIkdLI/c/kdRTOqo8t6ImVxg8yT7LQDUYV5Rp2FKeEosLr6ZCja9UjYAzyRSxGteSJPYg==} engines: {node: '>=12'} @@ -1514,8 +1447,8 @@ packages: requiresBuild: true optional: true - /@esbuild/android-x64@0.17.14: - resolution: {integrity: sha512-nrfQYWBfLGfSGLvRVlt6xi63B5IbfHm3tZCdu/82zuFPQ7zez4XjmRtF/wIRYbJQ/DsZrxJdEvYFE67avYXyng==} + /@esbuild/android-x64@0.17.12: + resolution: {integrity: sha512-m4OsaCr5gT+se25rFPHKQXARMyAehHTQAz4XX1Vk3d27VtqiX0ALMBPoXZsGaB6JYryCLfgGwUslMqTfqeLU0w==} engines: {node: '>=12'} cpu: [x64] os: [android] @@ -1530,8 +1463,8 @@ packages: requiresBuild: true optional: true - /@esbuild/darwin-arm64@0.17.14: - resolution: {integrity: sha512-eoSjEuDsU1ROwgBH/c+fZzuSyJUVXQTOIN9xuLs9dE/9HbV/A5IqdXHU1p2OfIMwBwOYJ9SFVGGldxeRCUJFyw==} + /@esbuild/darwin-arm64@0.17.12: + resolution: {integrity: sha512-O3GCZghRIx+RAN0NDPhyyhRgwa19MoKlzGonIb5hgTj78krqp9XZbYCvFr9N1eUxg0ZQEpiiZ4QvsOQwBpP+lg==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -1546,8 +1479,8 @@ packages: requiresBuild: true optional: true - /@esbuild/darwin-x64@0.17.14: - resolution: {integrity: sha512-zN0U8RWfrDttdFNkHqFYZtOH8hdi22z0pFm0aIJPsNC4QQZv7je8DWCX5iA4Zx6tRhS0CCc0XC2m7wKsbWEo5g==} + /@esbuild/darwin-x64@0.17.12: + resolution: {integrity: sha512-5D48jM3tW27h1qjaD9UNRuN+4v0zvksqZSPZqeSWggfMlsVdAhH3pwSfQIFJwcs9QJ9BRibPS4ViZgs3d2wsCA==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -1562,8 +1495,8 @@ packages: requiresBuild: true optional: true - /@esbuild/freebsd-arm64@0.17.14: - resolution: {integrity: sha512-z0VcD4ibeZWVQCW1O7szaLxGsx54gcCnajEJMdYoYjLiq4g1jrP2lMq6pk71dbS5+7op/L2Aod+erw+EUr28/A==} + /@esbuild/freebsd-arm64@0.17.12: + resolution: {integrity: sha512-OWvHzmLNTdF1erSvrfoEBGlN94IE6vCEaGEkEH29uo/VoONqPnoDFfShi41Ew+yKimx4vrmmAJEGNoyyP+OgOQ==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -1578,8 +1511,8 @@ packages: requiresBuild: true optional: true - /@esbuild/freebsd-x64@0.17.14: - resolution: {integrity: sha512-hd9mPcxfTgJlolrPlcXkQk9BMwNBvNBsVaUe5eNUqXut6weDQH8whcNaKNF2RO8NbpT6GY8rHOK2A9y++s+ehw==} + /@esbuild/freebsd-x64@0.17.12: + resolution: {integrity: sha512-A0Xg5CZv8MU9xh4a+7NUpi5VHBKh1RaGJKqjxe4KG87X+mTjDE6ZvlJqpWoeJxgfXHT7IMP9tDFu7IZ03OtJAw==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -1594,8 +1527,8 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-arm64@0.17.14: - resolution: {integrity: sha512-FhAMNYOq3Iblcj9i+K0l1Fp/MHt+zBeRu/Qkf0LtrcFu3T45jcwB6A1iMsemQ42vR3GBhjNZJZTaCe3VFPbn9g==} + /@esbuild/linux-arm64@0.17.12: + resolution: {integrity: sha512-cK3AjkEc+8v8YG02hYLQIQlOznW+v9N+OI9BAFuyqkfQFR+DnDLhEM5N8QRxAUz99cJTo1rLNXqRrvY15gbQUg==} engines: {node: '>=12'} cpu: [arm64] os: [linux] @@ -1610,8 +1543,8 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-arm@0.17.14: - resolution: {integrity: sha512-BNTl+wSJ1omsH8s3TkQmIIIQHwvwJrU9u1ggb9XU2KTVM4TmthRIVyxSp2qxROJHhZuW/r8fht46/QE8hU8Qvg==} + /@esbuild/linux-arm@0.17.12: + resolution: {integrity: sha512-WsHyJ7b7vzHdJ1fv67Yf++2dz3D726oO3QCu8iNYik4fb5YuuReOI9OtA+n7Mk0xyQivNTPbl181s+5oZ38gyA==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -1626,8 +1559,8 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-ia32@0.17.14: - resolution: {integrity: sha512-91OK/lQ5y2v7AsmnFT+0EyxdPTNhov3y2CWMdizyMfxSxRqHazXdzgBKtlmkU2KYIc+9ZK3Vwp2KyXogEATYxQ==} + /@esbuild/linux-ia32@0.17.12: + resolution: {integrity: sha512-jdOBXJqcgHlah/nYHnj3Hrnl9l63RjtQ4vn9+bohjQPI2QafASB5MtHAoEv0JQHVb/xYQTFOeuHnNYE1zF7tYw==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -1651,15 +1584,6 @@ packages: dev: true optional: true - /@esbuild/linux-loong64@0.17.11: - resolution: {integrity: sha512-aCWlq70Q7Nc9WDnormntGS1ar6ZFvUpqr8gXtO+HRejRYPweAFQN615PcgaSJkZjhHp61+MNLhzyVALSF2/Q0g==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.17.12: resolution: {integrity: sha512-GTOEtj8h9qPKXCyiBBnHconSCV9LwFyx/gv3Phw0pa25qPYjVuuGZ4Dk14bGCfGX3qKF0+ceeQvwmtI+aYBbVA==} engines: {node: '>=12'} @@ -1668,14 +1592,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-loong64@0.17.14: - resolution: {integrity: sha512-vp15H+5NR6hubNgMluqqKza85HcGJgq7t6rMH7O3Y6ApiOWPkvW2AJfNojUQimfTp6OUrACUXfR4hmpcENXoMQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-loong64@0.17.15: resolution: {integrity: sha512-k7FsUJjGGSxwnBmMh8d7IbObWu+sF/qbwc+xKZkBe/lTAF16RqxRCnNHA7QTd3oS2AfGBAnHlXL67shV5bBThQ==} engines: {node: '>=12'} @@ -1684,8 +1600,8 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-mips64el@0.17.14: - resolution: {integrity: sha512-90TOdFV7N+fgi6c2+GO9ochEkmm9kBAKnuD5e08GQMgMINOdOFHuYLPQ91RYVrnWwQ5683sJKuLi9l4SsbJ7Hg==} + /@esbuild/linux-mips64el@0.17.12: + resolution: {integrity: sha512-o8CIhfBwKcxmEENOH9RwmUejs5jFiNoDw7YgS0EJTF6kgPgcqLFjgoc5kDey5cMHRVCIWc6kK2ShUePOcc7RbA==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -1700,8 +1616,8 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-ppc64@0.17.14: - resolution: {integrity: sha512-NnBGeoqKkTugpBOBZZoktQQ1Yqb7aHKmHxsw43NddPB2YWLAlpb7THZIzsRsTr0Xw3nqiPxbA1H31ZMOG+VVPQ==} + /@esbuild/linux-ppc64@0.17.12: + resolution: {integrity: sha512-biMLH6NR/GR4z+ap0oJYb877LdBpGac8KfZoEnDiBKd7MD/xt8eaw1SFfYRUeMVx519kVkAOL2GExdFmYnZx3A==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -1716,8 +1632,8 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-riscv64@0.17.14: - resolution: {integrity: sha512-0qdlKScLXA8MGVy21JUKvMzCYWovctuP8KKqhtE5A6IVPq4onxXhSuhwDd2g5sRCzNDlDjitc5sX31BzDoL5Fw==} + /@esbuild/linux-riscv64@0.17.12: + resolution: {integrity: sha512-jkphYUiO38wZGeWlfIBMB72auOllNA2sLfiZPGDtOBb1ELN8lmqBrlMiucgL8awBw1zBXN69PmZM6g4yTX84TA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -1732,8 +1648,8 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-s390x@0.17.14: - resolution: {integrity: sha512-Hdm2Jo1yaaOro4v3+6/zJk6ygCqIZuSDJHdHaf8nVH/tfOuoEX5Riv03Ka15LmQBYJObUTNS1UdyoMk0WUn9Ww==} + /@esbuild/linux-s390x@0.17.12: + resolution: {integrity: sha512-j3ucLdeY9HBcvODhCY4b+Ds3hWGO8t+SAidtmWu/ukfLLG/oYDMaA+dnugTVAg5fnUOGNbIYL9TOjhWgQB8W5g==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -1748,8 +1664,8 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-x64@0.17.14: - resolution: {integrity: sha512-8KHF17OstlK4DuzeF/KmSgzrTWQrkWj5boluiiq7kvJCiQVzUrmSkaBvcLB2UgHpKENO2i6BthPkmUhNDaJsVw==} + /@esbuild/linux-x64@0.17.12: + resolution: {integrity: sha512-uo5JL3cgaEGotaqSaJdRfFNSCUJOIliKLnDGWaVCgIKkHxwhYMm95pfMbWZ9l7GeW9kDg0tSxcy9NYdEtjwwmA==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -1764,21 +1680,20 @@ packages: requiresBuild: true optional: true - /@esbuild/netbsd-x64@0.17.14: - resolution: {integrity: sha512-nVwpqvb3yyXztxIT2+VsxJhB5GCgzPdk1n0HHSnchRAcxqKO6ghXwHhJnr0j/B+5FSyEqSxF4q03rbA2fKXtUQ==} + /@esbuild/netbsd-x64@0.17.12: + resolution: {integrity: sha512-DNdoRg8JX+gGsbqt2gPgkgb00mqOgOO27KnrWZtdABl6yWTST30aibGJ6geBq3WM2TIeW6COs5AScnC7GwtGPg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] requiresBuild: true optional: true - /@esbuild/openbsd-x64@0.17.11: - resolution: {integrity: sha512-UBj135Nx4FpnvtE+C8TWGp98oUgBcmNmdYgl5ToKc0mBHxVVqVE7FUS5/ELMImOp205qDAittL6Ezhasc2Ev/w==} + /@esbuild/netbsd-x64@0.17.15: + resolution: {integrity: sha512-R6fKjtUysYGym6uXf6qyNephVUQAGtf3n2RCsOST/neIwPqRWcnc3ogcielOd6pT+J0RDR1RGcy0ZY7d3uHVLA==} engines: {node: '>=12'} cpu: [x64] - os: [openbsd] + os: [netbsd] requiresBuild: true - dev: true optional: true /@esbuild/openbsd-x64@0.17.12: @@ -1789,23 +1704,14 @@ packages: requiresBuild: true optional: true - /@esbuild/openbsd-x64@0.17.14: - resolution: {integrity: sha512-1RZ7uQQ9zcy/GSAJL1xPdN7NDdOOtNEGiJalg/MOzeakZeTrgH/DoCkbq7TaPDiPhWqnDF+4bnydxRqQD7il6g==} + /@esbuild/openbsd-x64@0.17.15: + resolution: {integrity: sha512-mVD4PGc26b8PI60QaPUltYKeSX0wxuy0AltC+WCTFwvKCq2+OgLP4+fFd+hZXzO2xW1HPKcytZBdjqL6FQFa7w==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] requiresBuild: true optional: true - /@esbuild/sunos-x64@0.17.11: - resolution: {integrity: sha512-1/gxTifDC9aXbV2xOfCbOceh5AlIidUrPsMpivgzo8P8zUtczlq1ncFpeN1ZyQJ9lVs2hILy1PG5KPp+w8QPPg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - /@esbuild/sunos-x64@0.17.12: resolution: {integrity: sha512-qbHGVQdKSwi0JQJuZznS4SyY27tYXYF0mrgthbxXrZI3AHKuRvU+Eqbg/F0rmLDpW/jkIZBlCO1XfHUBMNJ1pg==} engines: {node: '>=12'} @@ -1814,23 +1720,14 @@ packages: requiresBuild: true optional: true - /@esbuild/sunos-x64@0.17.14: - resolution: {integrity: sha512-nqMjDsFwv7vp7msrwWRysnM38Sd44PKmW8EzV01YzDBTcTWUpczQg6mGao9VLicXSgW/iookNK6AxeogNVNDZA==} + /@esbuild/sunos-x64@0.17.15: + resolution: {integrity: sha512-U6tYPovOkw3459t2CBwGcFYfFRjivcJJc1WC8Q3funIwX8x4fP+R6xL/QuTPNGOblbq/EUDxj9GU+dWKX0oWlQ==} engines: {node: '>=12'} cpu: [x64] os: [sunos] requiresBuild: true optional: true - /@esbuild/win32-arm64@0.17.11: - resolution: {integrity: sha512-vtSfyx5yRdpiOW9yp6Ax0zyNOv9HjOAw8WaZg3dF5djEHKKm3UnoohftVvIJtRh0Ec7Hso0RIdTqZvPXJ7FdvQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-arm64@0.17.12: resolution: {integrity: sha512-zsCp8Ql+96xXTVTmm6ffvoTSZSV2B/LzzkUXAY33F/76EajNw1m+jZ9zPfNJlJ3Rh4EzOszNDHsmG/fZOhtqDg==} engines: {node: '>=12'} @@ -1839,72 +1736,6 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-arm64@0.17.14: - resolution: {integrity: sha512-xrD0mccTKRBBIotrITV7WVQAwNJ5+1va6L0H9zN92v2yEdjfAN7864cUaZwJS7JPEs53bDTzKFbfqVlG2HhyKQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/win32-ia32@0.17.11: - resolution: {integrity: sha512-GFPSLEGQr4wHFTiIUJQrnJKZhZjjq4Sphf+mM76nQR6WkQn73vm7IsacmBRPkALfpOCHsopSvLgqdd4iUW2mYw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.17.15: - resolution: {integrity: sha512-R6fKjtUysYGym6uXf6qyNephVUQAGtf3n2RCsOST/neIwPqRWcnc3ogcielOd6pT+J0RDR1RGcy0ZY7d3uHVLA==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - optional: true - - /@esbuild/openbsd-x64@0.17.14: - resolution: {integrity: sha512-1RZ7uQQ9zcy/GSAJL1xPdN7NDdOOtNEGiJalg/MOzeakZeTrgH/DoCkbq7TaPDiPhWqnDF+4bnydxRqQD7il6g==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/openbsd-x64@0.17.15: - resolution: {integrity: sha512-mVD4PGc26b8PI60QaPUltYKeSX0wxuy0AltC+WCTFwvKCq2+OgLP4+fFd+hZXzO2xW1HPKcytZBdjqL6FQFa7w==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - optional: true - - /@esbuild/sunos-x64@0.17.14: - resolution: {integrity: sha512-nqMjDsFwv7vp7msrwWRysnM38Sd44PKmW8EzV01YzDBTcTWUpczQg6mGao9VLicXSgW/iookNK6AxeogNVNDZA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/sunos-x64@0.17.15: - resolution: {integrity: sha512-U6tYPovOkw3459t2CBwGcFYfFRjivcJJc1WC8Q3funIwX8x4fP+R6xL/QuTPNGOblbq/EUDxj9GU+dWKX0oWlQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - optional: true - - /@esbuild/win32-arm64@0.17.14: - resolution: {integrity: sha512-xrD0mccTKRBBIotrITV7WVQAwNJ5+1va6L0H9zN92v2yEdjfAN7864cUaZwJS7JPEs53bDTzKFbfqVlG2HhyKQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-arm64@0.17.15: resolution: {integrity: sha512-W+Z5F++wgKAleDABemiyXVnzXgvRFs+GVKThSI+mGgleLWluv0D7Diz4oQpgdpNzh4i2nNDzQtWbjJiqutRp6Q==} engines: {node: '>=12'} @@ -1913,10 +1744,10 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-ia32@0.17.14: - resolution: {integrity: sha512-nXpkz9bbJrLLyUTYtRotSS3t5b+FOuljg8LgLdINWFs3FfqZMtbnBCZFUmBzQPyxqU87F8Av+3Nco/M3hEcu1w==} + /@esbuild/win32-ia32@0.17.12: + resolution: {integrity: sha512-FfrFjR4id7wcFYOdqbDfDET3tjxCozUgbqdkOABsSFzoZGFC92UK7mg4JKRc/B3NNEf1s2WHxJ7VfTdVDPN3ng==} engines: {node: '>=12'} - cpu: [x64] + cpu: [ia32] os: [win32] requiresBuild: true optional: true @@ -1929,8 +1760,8 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-x64@0.17.14: - resolution: {integrity: sha512-gPQmsi2DKTaEgG14hc3CHXHp62k8g6qr0Pas+I4lUxRMugGSATh/Bi8Dgusoz9IQ0IfdrvLpco6kujEIBoaogA==} + /@esbuild/win32-x64@0.17.12: + resolution: {integrity: sha512-JOOxw49BVZx2/5tW3FqkdjSD/5gXYeVGPDcB0lvap0gLQshkh1Nyel1QazC+wNxus3xPlsYAgqU1BUmrmCvWtw==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -2267,19 +2098,6 @@ packages: /@polka/url@1.0.0-next.21: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} - /@rollup/plugin-alias@4.0.3(rollup@3.19.1): - resolution: {integrity: sha512-ZuDWE1q4PQDhvm/zc5Prun8sBpLJy41DMptYrS6MhAy9s9kL/doN1613BWfEchGVfKxzliJ3BjbOPizXX38DbQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - rollup: 3.19.1 - slash: 4.0.0 - dev: true - /@rollup/plugin-alias@4.0.3(rollup@3.20.2): resolution: {integrity: sha512-ZuDWE1q4PQDhvm/zc5Prun8sBpLJy41DMptYrS6MhAy9s9kL/doN1613BWfEchGVfKxzliJ3BjbOPizXX38DbQ==} engines: {node: '>=14.0.0'} @@ -2292,24 +2110,6 @@ packages: rollup: 3.20.2 slash: 4.0.0 - /@rollup/plugin-commonjs@24.0.1(rollup@3.19.1): - resolution: {integrity: sha512-15LsiWRZk4eOGqvrJyu3z3DaBu5BhXIMeWnijSRvd8irrrg9SHpQ1pH+BUK4H6Z9wL9yOxZJMTLU+Au86XHxow==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.68.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.19.1) - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 8.1.0 - is-reference: 1.2.1 - magic-string: 0.30.0 - rollup: 3.19.1 - dev: true - /@rollup/plugin-commonjs@24.0.1(rollup@3.20.2): resolution: {integrity: sha512-15LsiWRZk4eOGqvrJyu3z3DaBu5BhXIMeWnijSRvd8irrrg9SHpQ1pH+BUK4H6Z9wL9yOxZJMTLU+Au86XHxow==} engines: {node: '>=14.0.0'} @@ -2341,19 +2141,6 @@ packages: magic-string: 0.30.0 rollup: 3.20.2 - /@rollup/plugin-json@6.0.0(rollup@3.19.1): - resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.19.1) - rollup: 3.19.1 - dev: true - /@rollup/plugin-json@6.0.0(rollup@3.20.2): resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==} engines: {node: '>=14.0.0'} @@ -2366,24 +2153,6 @@ packages: '@rollup/pluginutils': 5.0.2(rollup@3.20.2) rollup: 3.20.2 - /@rollup/plugin-node-resolve@15.0.1(rollup@3.19.1): - resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.19.1) - '@types/resolve': 1.20.2 - deepmerge: 4.3.0 - is-builtin-module: 3.2.1 - is-module: 1.0.0 - resolve: 1.22.1 - rollup: 3.19.1 - dev: true - /@rollup/plugin-node-resolve@15.0.1(rollup@3.20.2): resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} engines: {node: '>=14.0.0'} @@ -2401,20 +2170,6 @@ packages: resolve: 1.22.1 rollup: 3.20.2 - /@rollup/plugin-replace@5.0.2(rollup@3.19.1): - resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.19.1) - magic-string: 0.30.0 - rollup: 3.19.1 - dev: true - /@rollup/plugin-replace@5.0.2(rollup@3.20.2): resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==} engines: {node: '>=14.0.0'} @@ -2460,20 +2215,6 @@ packages: estree-walker: 2.0.2 picomatch: 2.3.1 - /@rollup/pluginutils@5.0.2(rollup@3.19.1): - resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.0 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 3.19.1 - /@rollup/pluginutils@5.0.2(rollup@3.20.2): resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} @@ -3150,14 +2891,6 @@ packages: vite: 4.2.1(@types/node@18.15.11) vue: 3.2.47 - /@vitest/expect@0.29.7: - resolution: {integrity: sha512-UtG0tW0DP6b3N8aw7PHmweKDsvPv4wjGvrVZW7OSxaFg76ShtVdMiMcUkZJgCE8QWUmhwaM0aQhbbVLo4F4pkA==} - dependencies: - '@vitest/spy': 0.29.7 - '@vitest/utils': 0.29.7 - chai: 4.3.7 - dev: true - /@vitest/expect@0.29.8: resolution: {integrity: sha512-xlcVXn5I5oTq6NiZSY3ykyWixBxr5mG8HYtjvpgg6KaqHm0mvhX18xuwl5YGxIRNt/A5jidd7CWcNHrSvgaQqQ==} dependencies: @@ -3166,14 +2899,6 @@ packages: chai: 4.3.7 dev: true - /@vitest/runner@0.29.7: - resolution: {integrity: sha512-Yt0+csM945+odOx4rjZSjibQfl2ymxqVsmYz6sO2fiO5RGPYDFCo60JF6tLL9pz4G/kjY4irUxadeB1XT+H1jg==} - dependencies: - '@vitest/utils': 0.29.7 - p-limit: 4.0.0 - pathe: 1.1.0 - dev: true - /@vitest/runner@0.29.8: resolution: {integrity: sha512-FzdhnRDwEr/A3Oo1jtIk/B952BBvP32n1ObMEb23oEJNO+qO5cBet6M2XWIDQmA7BDKGKvmhUf2naXyp/2JEwQ==} dependencies: @@ -3182,27 +2907,12 @@ packages: pathe: 1.1.0 dev: true - /@vitest/spy@0.29.7: - resolution: {integrity: sha512-IalL0iO6A6Xz8hthR8sctk6ZS//zVBX48EiNwQguYACdgdei9ZhwMaBFV70mpmeYAFCRAm+DpoFHM5470Im78A==} - dependencies: - tinyspy: 1.1.1 - dev: true - /@vitest/spy@0.29.8: resolution: {integrity: sha512-VdjBe9w34vOMl5I5mYEzNX8inTxrZ+tYUVk9jxaZJmHFwmDFC/GV3KBFTA/JKswr3XHvZL+FE/yq5EVhb6pSAw==} dependencies: tinyspy: 1.1.1 dev: true - /@vitest/utils@0.29.7: - resolution: {integrity: sha512-vNgGadp2eE5XKCXtZXL5UyNEDn68npSct75OC9AlELenSK0DiV1Mb9tfkwJHKjRb69iek+e79iipoJx8+s3SdA==} - dependencies: - cli-truncate: 3.1.0 - diff: 5.1.0 - loupe: 2.3.6 - pretty-format: 27.5.1 - dev: true - /@vitest/utils@0.29.8: resolution: {integrity: sha512-qGzuf3vrTbnoY+RjjVVIBYfuWMjn3UMUqyQtdGNZ6ZIIyte7B37exj6LaVkrZiUTvzSadVvO/tJm8AEgbGCBPg==} dependencies: @@ -3255,8 +2965,8 @@ packages: '@babel/helper-module-imports': 7.18.6 '@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.21.3) '@babel/template': 7.20.7 - '@babel/traverse': 7.21.3 - '@babel/types': 7.21.3 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 '@vue/babel-helper-vue-transform-on': 1.0.2 camelcase: 6.3.0 html-tags: 3.2.0 @@ -3268,7 +2978,7 @@ packages: /@vue/compiler-core@3.2.47: resolution: {integrity: sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==} dependencies: - '@babel/parser': 7.21.3 + '@babel/parser': 7.21.4 '@vue/shared': 3.2.47 estree-walker: 2.0.2 source-map: 0.6.1 @@ -3306,7 +3016,7 @@ packages: /@vue/reactivity-transform@3.2.47: resolution: {integrity: sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==} dependencies: - '@babel/parser': 7.21.3 + '@babel/parser': 7.21.4 '@vue/compiler-core': 3.2.47 '@vue/shared': 3.2.47 estree-walker: 2.0.2 @@ -5096,36 +4806,6 @@ packages: esbuild-windows-arm64: 0.15.18 dev: true - /esbuild@0.17.11: - resolution: {integrity: sha512-pAMImyokbWDtnA/ufPxjQg0fYo2DDuzAlqwnDvbXqHLphe+m80eF++perYKVm8LeTuj2zUuFXC+xgSVxyoHUdg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.17.11 - '@esbuild/android-arm64': 0.17.11 - '@esbuild/android-x64': 0.17.11 - '@esbuild/darwin-arm64': 0.17.11 - '@esbuild/darwin-x64': 0.17.11 - '@esbuild/freebsd-arm64': 0.17.11 - '@esbuild/freebsd-x64': 0.17.11 - '@esbuild/linux-arm': 0.17.11 - '@esbuild/linux-arm64': 0.17.11 - '@esbuild/linux-ia32': 0.17.11 - '@esbuild/linux-loong64': 0.17.11 - '@esbuild/linux-mips64el': 0.17.11 - '@esbuild/linux-ppc64': 0.17.11 - '@esbuild/linux-riscv64': 0.17.11 - '@esbuild/linux-s390x': 0.17.11 - '@esbuild/linux-x64': 0.17.11 - '@esbuild/netbsd-x64': 0.17.11 - '@esbuild/openbsd-x64': 0.17.11 - '@esbuild/sunos-x64': 0.17.11 - '@esbuild/win32-arm64': 0.17.11 - '@esbuild/win32-ia32': 0.17.11 - '@esbuild/win32-x64': 0.17.11 - dev: true - /esbuild@0.17.12: resolution: {integrity: sha512-bX/zHl7Gn2CpQwcMtRogTTBf9l1nl+H6R8nUbjk+RuKqAE3+8FDulLA+pHvX7aA7Xe07Iwa+CWvy9I8Y2qqPKQ==} engines: {node: '>=12'} @@ -5155,35 +4835,6 @@ packages: '@esbuild/win32-ia32': 0.17.12 '@esbuild/win32-x64': 0.17.12 - /esbuild@0.17.14: - resolution: {integrity: sha512-vOO5XhmVj/1XQR9NQ1UPq6qvMYL7QFJU57J5fKBKBKxp17uDt5PgxFDb4A2nEiXhr1qQs4x0F5+66hVVw4ruNw==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.17.14 - '@esbuild/android-arm64': 0.17.14 - '@esbuild/android-x64': 0.17.14 - '@esbuild/darwin-arm64': 0.17.14 - '@esbuild/darwin-x64': 0.17.14 - '@esbuild/freebsd-arm64': 0.17.14 - '@esbuild/freebsd-x64': 0.17.14 - '@esbuild/linux-arm': 0.17.14 - '@esbuild/linux-arm64': 0.17.14 - '@esbuild/linux-ia32': 0.17.14 - '@esbuild/linux-loong64': 0.17.14 - '@esbuild/linux-mips64el': 0.17.14 - '@esbuild/linux-ppc64': 0.17.14 - '@esbuild/linux-riscv64': 0.17.14 - '@esbuild/linux-s390x': 0.17.14 - '@esbuild/linux-x64': 0.17.14 - '@esbuild/netbsd-x64': 0.17.14 - '@esbuild/openbsd-x64': 0.17.14 - '@esbuild/sunos-x64': 0.17.14 - '@esbuild/win32-arm64': 0.17.14 - '@esbuild/win32-ia32': 0.17.14 - '@esbuild/win32-x64': 0.17.14 - /esbuild@0.17.15: resolution: {integrity: sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw==} engines: {node: '>=12'} @@ -6188,10 +5839,6 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - /hookable@5.5.1: - resolution: {integrity: sha512-ac50aYjbtRMMZEtTG0qnVaBDA+1lqL9fHzDnxMQlVuO6LZWcBB7NXjIu9H9iImClewNdrit4RiEzi9QpRTgKrg==} - dev: true - /hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} @@ -7103,7 +6750,7 @@ packages: resolution: {integrity: sha512-UTqu/bXmIk/+VKNVgufAeMyjUcNy1dn9Bl7wL1zZlCKVrpDgj/VllmZBeh3ZCC/2HWqUrt6frNFTKt9TRZbNvQ==} hasBin: true peerDependencies: - sass: ^1.58.3 + sass: ^1.60.0 typescript: '>=4.9.5' peerDependenciesMeta: sass: @@ -7546,7 +7193,7 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.21.4 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -8321,13 +7968,6 @@ packages: fsevents: 2.3.2 dev: true - /rollup@3.19.1: - resolution: {integrity: sha512-lAbrdN7neYCg/8WaoWn/ckzCtz+jr70GFfYdlf50OF7387HTg+wiuiqJRFYawwSPpqfqDNYqK7smY/ks2iAudg==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true - optionalDependencies: - fsevents: 2.3.2 - /rollup@3.20.0: resolution: {integrity: sha512-YsIfrk80NqUDrxrjWPXUa7PWvAfegZEXHuPsEZg58fGCdjL1I9C1i/NaG+L+27kxxwkrG/QEDEQc8s/ynXWWGQ==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} @@ -9084,18 +8724,18 @@ packages: resolution: {integrity: sha512-GcolNMBatav7FbRdLDR8BMbnYWMoKfxXdJIHibpBtx3GERN4GbbUD5h4RfGIFi+mjWPz4AphSz5gIg9FWNWw3Q==} hasBin: true dependencies: - '@rollup/plugin-alias': 4.0.3(rollup@3.19.1) - '@rollup/plugin-commonjs': 24.0.1(rollup@3.19.1) - '@rollup/plugin-json': 6.0.0(rollup@3.19.1) - '@rollup/plugin-node-resolve': 15.0.1(rollup@3.19.1) - '@rollup/plugin-replace': 5.0.2(rollup@3.19.1) - '@rollup/pluginutils': 5.0.2(rollup@3.19.1) + '@rollup/plugin-alias': 4.0.3(rollup@3.20.2) + '@rollup/plugin-commonjs': 24.0.1(rollup@3.20.2) + '@rollup/plugin-json': 6.0.0(rollup@3.20.2) + '@rollup/plugin-node-resolve': 15.0.1(rollup@3.20.2) + '@rollup/plugin-replace': 5.0.2(rollup@3.20.2) + '@rollup/pluginutils': 5.0.2(rollup@3.20.2) chalk: 5.2.0 consola: 2.15.3 defu: 6.1.2 - esbuild: 0.17.11 + esbuild: 0.17.15 globby: 13.1.3 - hookable: 5.5.1 + hookable: 5.5.3 jiti: 1.18.2 magic-string: 0.30.0 mkdist: 1.2.0(typescript@5.0.3) @@ -9158,24 +8798,6 @@ packages: hookable: 5.5.3 dev: false - /unimport@3.0.4(rollup@3.19.1): - resolution: {integrity: sha512-eoof/HLiNJcIkVpnqc7sJbzKSLx39J6xTaP7E4ElgVQKeq2t9fPTkvJKcA55IJTaRPkEkDq8kcc/IZPmrypnFg==} - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.19.1) - escape-string-regexp: 5.0.0 - fast-glob: 3.2.12 - local-pkg: 0.4.3 - magic-string: 0.30.0 - mlly: 1.2.0 - pathe: 1.1.0 - pkg-types: 1.0.2 - scule: 1.0.0 - strip-literal: 1.0.1 - unplugin: 1.3.1 - transitivePeerDependencies: - - rollup - dev: false - /unimport@3.0.4(rollup@3.20.2): resolution: {integrity: sha512-eoof/HLiNJcIkVpnqc7sJbzKSLx39J6xTaP7E4ElgVQKeq2t9fPTkvJKcA55IJTaRPkEkDq8kcc/IZPmrypnFg==} dependencies: @@ -9305,9 +8927,9 @@ packages: resolution: {integrity: sha512-z219Z65rOGD6jXIvIhpZFfwWdqQckB8sdZec2NO+TkcH1Bph7gL0hwLzRJs1KsOo4Jz4mF9guBXhsEnyEBGVfw==} hasBin: true dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.21.4 '@babel/standalone': 7.21.3 - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 defu: 6.1.2 jiti: 1.18.2 mri: 1.2.0 @@ -9377,27 +8999,6 @@ packages: extsprintf: 1.3.0 dev: true - /vite-node@0.29.7(@types/node@18.15.11): - resolution: {integrity: sha512-PakCZLvz37yFfUPWBnLa1OYHPCGm5v4pmRrTcFN4V/N/T3I6tyP3z07S//9w+DdeL7vVd0VSeyMZuAh+449ZWw==} - engines: {node: '>=v14.16.0'} - hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.3.4 - mlly: 1.2.0 - pathe: 1.1.0 - picocolors: 1.0.0 - vite: 4.2.1(@types/node@18.15.11) - transitivePeerDependencies: - - '@types/node' - - less - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - /vite-node@0.29.8(@types/node@18.15.11): resolution: {integrity: sha512-b6OtCXfk65L6SElVM20q5G546yu10/kNrhg08afEoWlFRJXFq9/6glsvSVY+aI6YeC1tu2TtAqI2jHEQmOmsFw==} engines: {node: '>=v14.16.0'} @@ -9538,67 +9139,6 @@ packages: optionalDependencies: fsevents: 2.3.2 - /vitest@0.29.7: - resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} - engines: {node: '>=v14.16.0'} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@vitest/browser': '*' - '@vitest/ui': '*' - happy-dom: '*' - jsdom: '*' - safaridriver: '*' - webdriverio: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - safaridriver: - optional: true - webdriverio: - optional: true - dependencies: - '@types/chai': 4.3.4 - '@types/chai-subset': 1.3.3 - '@types/node': 18.15.11 - '@vitest/expect': 0.29.7 - '@vitest/runner': 0.29.7 - '@vitest/spy': 0.29.7 - '@vitest/utils': 0.29.7 - acorn: 8.8.2 - acorn-walk: 8.2.0 - cac: 6.7.14 - chai: 4.3.7 - debug: 4.3.4 - local-pkg: 0.4.3 - pathe: 1.1.0 - picocolors: 1.0.0 - source-map: 0.6.1 - std-env: 3.3.2 - strip-literal: 1.0.1 - tinybench: 2.4.0 - tinypool: 0.4.0 - tinyspy: 1.1.1 - vite: 4.2.1(@types/node@18.15.11) - vite-node: 0.29.7(@types/node@18.15.11) - why-is-node-running: 2.2.2 - transitivePeerDependencies: - - less - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - /vitest@0.29.8(playwright@1.32.1): resolution: {integrity: sha512-JIAVi2GK5cvA6awGpH0HvH/gEG9PZ0a/WoxdiV3PmqK+3CjQMf8c+J/Vhv4mdZ2nRyXFw66sAg6qz7VNkaHfDQ==} engines: {node: '>=v14.16.0'} From 8f4395ec3ace9de7407a8e9b0674d567c461f7dc Mon Sep 17 00:00:00 2001 From: julien huang Date: Mon, 3 Apr 2023 20:53:09 +0200 Subject: [PATCH 29/63] chore: update bundle size --- test/bundle.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bundle.test.ts b/test/bundle.test.ts index 8a767d3a9f28..04c74e62dd65 100644 --- a/test/bundle.test.ts +++ b/test/bundle.test.ts @@ -43,7 +43,7 @@ describe.skipIf(isWindows || process.env.ECOSYSTEM_CI)('minimal nuxt application expect(stats.server.totalBytes).toBeLessThan(94450) const modules = await analyzeSizes('node_modules/**/*', serverDir) - expect(modules.totalBytes).toBeLessThan(2694900) + expect(modules.totalBytes).toBeLessThan(2695150) const packages = modules.files .filter(m => m.endsWith('package.json')) From 0ceb7bc3a22d0ddf10fce2d71283cb88ae5b551b Mon Sep 17 00:00:00 2001 From: julien huang Date: Tue, 11 Apr 2023 06:50:12 +0200 Subject: [PATCH 30/63] WIP slot state --- .../src/app/components/island-renderer.ts | 12 +-- .../nuxt/src/app/components/nuxt-island.ts | 8 +- .../nuxt/src/components/islandsTransform.ts | 74 +++++++++++++++++++ packages/nuxt/src/components/module.ts | 9 +++ .../nuxt/src/core/runtime/nitro/renderer.ts | 2 +- test/basic.test.ts | 12 +-- .../components/islands/LongAsyncComponent.vue | 2 +- 7 files changed, 99 insertions(+), 20 deletions(-) create mode 100644 packages/nuxt/src/components/islandsTransform.ts diff --git a/packages/nuxt/src/app/components/island-renderer.ts b/packages/nuxt/src/app/components/island-renderer.ts index 447445c2b90e..3ecf9668c3a2 100644 --- a/packages/nuxt/src/app/components/island-renderer.ts +++ b/packages/nuxt/src/app/components/island-renderer.ts @@ -16,15 +16,7 @@ export default defineComponent({ setup (props) { const uid = props.context.uid ?? randomUUID() const component = islandComponents[props.context.name] as ReturnType - const slots: Record = {} - if (props.context.slotsName) { - for (const slotName of props.context.slotsName) { - slots[slotName] = () => { - return createVNode('div', { 'v-ssr-slot-name': slotName, style: 'display: contents;' }) - } - } - } - + if (!component) { throw createError({ statusCode: 404, @@ -32,6 +24,6 @@ export default defineComponent({ }) } - return () => createVNode(component || 'span', { ...props.context.props, 'v-ssr-component-uid': uid }, slots) + return () => createVNode(component || 'span', { ...props.context.props, 'nuxt-ssr-component-uid': uid }) } }) diff --git a/packages/nuxt/src/app/components/nuxt-island.ts b/packages/nuxt/src/app/components/nuxt-island.ts index eee44c27b8d5..d9c29ae615a2 100644 --- a/packages/nuxt/src/app/components/nuxt-island.ts +++ b/packages/nuxt/src/app/components/nuxt-island.ts @@ -12,7 +12,7 @@ import { useNuxtApp } from '#app/nuxt' import { useRequestEvent } from '#app/composables/ssr' const pKey = '_islandPromises' -const SSR_UID_RE = /v-ssr-component-uid="([^"]*)"/ +const SSR_UID_RE = /nuxt-ssr-component-uid="([^"]*)"/ export default defineComponent({ name: 'NuxtIsland', @@ -45,6 +45,10 @@ export default defineComponent({ } const cHead = ref>>>({ link: [], style: [] }) useHead(cHead) + const slotProps = computed(() => { + + return {} + }) function _fetchComponent () { const url = `/__nuxt_island/${props.name}:${hashId.value}` @@ -100,7 +104,7 @@ export default defineComponent({ }, [h(createStaticVNode(html.value, 1))])] if (uid.value) { for (const slot in slots) { - nodes.push(createVNode(Teleport, { to: process.client ? `[v-ssr-component-uid='${uid.value}'] [v-ssr-slot-name='${slot}']` : `uid=${uid.value};slot=${slot}` }, { + nodes.push(createVNode(Teleport, { to: process.client ? `[nuxt-ssr-component-uid='${uid.value}'] [ssr-slot-name='${slot}']` : `uid=${uid.value};slot=${slot}` }, { default: () => [slots[slot]?.()] })) } diff --git a/packages/nuxt/src/components/islandsTransform.ts b/packages/nuxt/src/components/islandsTransform.ts new file mode 100644 index 000000000000..34ffa3aa3dab --- /dev/null +++ b/packages/nuxt/src/components/islandsTransform.ts @@ -0,0 +1,74 @@ +import { pathToFileURL } from 'node:url' +import type { Component } from '@nuxt/schema' +import { parseURL } from 'ufo' +import { createUnplugin } from 'unplugin' +import MagicString from 'magic-string' + +interface ServerOnlyComponentTransformPluginOptions { + getComponents: () => Component[] +} + +const ATTRS_RE = /([^=]*)="([^"]*)"/g + +export const islandsTransform = createUnplugin((options: ServerOnlyComponentTransformPluginOptions) => { + return { + name: 'server-only-component-transform', + enforce: 'pre', + transformInclude (id) { + const components = options.getComponents() + const islands = components.filter(component => + component.island || (component.mode === 'server' && !components.some(c => c.pascalName === component.pascalName && c.mode === 'client')) + ) + const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href)) + return islands.some(c => c.filePath === pathname) && !id.includes('NuxtIsland') + }, + transform (code, id) { + if (!code.includes(']*)\/?>/g, (_, attrs: string) => { + let slotName = 'default' + const bindings: Record = {} + const parsedAttrs = attrs.replaceAll(ATTRS_RE, (matched, name, value) => { + name = name.trim() + if (name.startsWith('v-')) { + return matched + } + if (name !== 'name') { + if (name === 'v-bind') { + bindings._bind = value + } else { + bindings[name] = value + } + } else { + slotName = value + } + return '' + }) + const ssrScopeData = getBindings(bindings) + + return `
` + }) + s.replaceAll('', '
') + + if (s.hasChanged()) { + return { + code: s.toString(), + map: s.generateMap({ source: id, includeContent: true }) + + } + } + } + } +}) + +function isBinding (attr: string): boolean { + return attr.startsWith(':') +} + +function getBindings (bindings: Record): string { + if (Object.keys(bindings).length === 0) { return '' } + + const content = Object.entries(bindings).map(([name, value]) => isBinding(name) ? `${name.slice(1)}: ${value}` : `${name}: \`${value}\``).join(',') + return `:ssr-slot-data="JSON.stringify({ ${content} })"` +} diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index a8139e727d6a..8e15b893db73 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -9,6 +9,7 @@ import { componentsPluginTemplate, componentsTemplate, componentsIslandsTemplate import { scanComponents } from './scan' import { loaderPlugin } from './loader' import { TreeShakeTemplatePlugin } from './tree-shake' +import { islandsTransform } from './islandsTransform' const isPureObjectOrString = (val: any) => (!Array.isArray(val) && typeof val === 'object') || typeof val === 'string' const isDirectory = (p: string) => { try { return statSync(p).isDirectory() } catch (_e) { return false } } @@ -222,6 +223,10 @@ export default defineNuxtModule({ transform: typeof nuxt.options.components === 'object' && !Array.isArray(nuxt.options.components) ? nuxt.options.components.transform : undefined, experimentalComponentIslands: nuxt.options.experimental.componentIslands })) + + config.plugins.push(islandsTransform.vite({ + getComponents + })) }) nuxt.hook('webpack:config', (configs) => { configs.forEach((config) => { @@ -244,6 +249,10 @@ export default defineNuxtModule({ transform: typeof nuxt.options.components === 'object' && !Array.isArray(nuxt.options.components) ? nuxt.options.components.transform : undefined, experimentalComponentIslands: nuxt.options.experimental.componentIslands })) + + config.plugins.push(islandsTransform.webpack({ + getComponents + })) }) }) } diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index dd9306224340..be2532266643 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -457,7 +457,7 @@ function replaceServerOnlyComponentsSlots (ssrContext: NuxtSSRContext, html: str if (!match) { continue } const [, uid, slot] = match if (!uid || !slot) { continue } - html = html.replace(new RegExp(`
((?!v-ssr-slot-name="${slot}"|v-ssr-component-uid).)*
]*)>`), (full) => { + html = html.replace(new RegExp(`
((?!ssr-slot-name="${slot}"|nuxt-ssr-component-uid).)*
]*)>`), (full) => { return full + teleports[key] }) } diff --git a/test/basic.test.ts b/test/basic.test.ts index 849a3f182df1..9621e82082a9 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -75,7 +75,7 @@ describe('pages', () => { // should apply attributes to client-only components expect(html).toContain('
') // should render server-only components - expect(html.replace(/ v-ssr-component-uid="([^"]*)"/g, '')).toContain('
server-only component
') + expect(html.replace(/ nuxt-ssr-component-uid="([^"]*)"/g, '')).toContain('
server-only component
') // should register global components automatically expect(html).toContain('global component registered automatically') expect(html).toContain('global component via suffix') @@ -1086,7 +1086,7 @@ describe('app config', () => { describe('component islands', () => { it('renders components with route', async () => { const result: NuxtIslandResponse = await $fetch('/__nuxt_island/RouteComponent?url=/foo') - result.html = result.html.replace(/ v-ssr-component-uid="([^"]*)"/g, '') + result.html = result.html.replace(/ nuxt-ssr-component-uid="([^"]*)"/g, '') 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/RouteComponent'))) @@ -1114,7 +1114,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.replace(/ v-ssr-component-uid="([^"]*)"/g, '') + result.html = result.html.replace(/ nuxt-ssr-component-uid="([^"]*)"/g, '') expect(result).toMatchInlineSnapshot(` { "head": { @@ -1136,7 +1136,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/AsyncServerComponent'))) } - result.html = result.html.replace(/ v-ssr-component-uid="([^"]*)"/g, '') + result.html = result.html.replace(/ nuxt-ssr-component-uid="([^"]*)"/g, '') expect(result).toMatchInlineSnapshot(` { "head": { @@ -1158,7 +1158,7 @@ describe('component islands', () => { obj: { foo: 42, bar: false, me: 'hi' } }) })) - result.html = result.html.replace(/ v-ssr-component-uid="([^"]*)"/g, '') + result.html = result.html.replace(/ nuxt-ssr-component-uid="([^"]*)"/g, '') if (isDev()) { result.head.link = result.head.link.filter(l => !l.href.includes('@nuxt+ui-templates')) @@ -1202,7 +1202,7 @@ describe('component islands', () => { `) } - expect(result.html.replace(/data-v-\w+|"|/g, '').replace(/v-ssr-component-uid="([^"]*)"/g, '')).toMatchInlineSnapshot(` + expect(result.html.replace(/data-v-\w+|"|/g, '').replace(/nuxt-ssr-component-uid="([^"]*)"/g, '')).toMatchInlineSnapshot(` "
Was router enabled: true
Props:
{
       number: 3487,
       str: something,
diff --git a/test/fixtures/basic/components/islands/LongAsyncComponent.vue b/test/fixtures/basic/components/islands/LongAsyncComponent.vue
index 4f9f41b3c8a8..2069bb4d4c24 100644
--- a/test/fixtures/basic/components/islands/LongAsyncComponent.vue
+++ b/test/fixtures/basic/components/islands/LongAsyncComponent.vue
@@ -8,7 +8,7 @@
     
{{ count }}
- +

hello world !!!

From d0ecbc79df8caa8e643f431bfb48856c68cda409 Mon Sep 17 00:00:00 2001 From: julien huang Date: Wed, 12 Apr 2023 23:18:53 +0200 Subject: [PATCH 31/63] feat: first working slot implementation --- .../src/app/components/island-renderer.ts | 2 +- .../nuxt/src/app/components/nuxt-island.ts | 22 ++++++++++++++----- packages/nuxt/src/app/components/utils.ts | 18 +++++++++++++++ .../nuxt/src/components/islandsTransform.ts | 8 +++---- .../nuxt/src/core/runtime/nitro/renderer.ts | 2 +- test/fixtures/basic/pages/islands.vue | 4 ++-- 6 files changed, 42 insertions(+), 14 deletions(-) diff --git a/packages/nuxt/src/app/components/island-renderer.ts b/packages/nuxt/src/app/components/island-renderer.ts index 3ecf9668c3a2..8febb9ecc5fc 100644 --- a/packages/nuxt/src/app/components/island-renderer.ts +++ b/packages/nuxt/src/app/components/island-renderer.ts @@ -16,7 +16,7 @@ export default defineComponent({ setup (props) { const uid = props.context.uid ?? randomUUID() const component = islandComponents[props.context.name] as ReturnType - + if (!component) { throw createError({ statusCode: 404, diff --git a/packages/nuxt/src/app/components/nuxt-island.ts b/packages/nuxt/src/app/components/nuxt-island.ts index d9c29ae615a2..370932150130 100644 --- a/packages/nuxt/src/app/components/nuxt-island.ts +++ b/packages/nuxt/src/app/components/nuxt-island.ts @@ -1,5 +1,6 @@ +import destr from 'destr' import type { VNode, RendererNode } from 'vue' -import { nextTick, h, Fragment, defineComponent, createStaticVNode, computed, ref, watch, getCurrentInstance, Teleport, onMounted, createVNode } from 'vue' +import { nextTick, h, Fragment, defineComponent, createStaticVNode, computed, ref, watch, getCurrentInstance, Teleport, onMounted, createVNode, mergeProps } from 'vue' import { debounce } from 'perfect-debounce' import { hash } from 'ohash' @@ -8,6 +9,7 @@ import { useHead } from '@unhead/vue' import { randomUUID } from 'uncrypto' // eslint-disable-next-line import/no-restricted-paths import type { NuxtIslandResponse } from '../../core/runtime/nitro/renderer' +import { decodeHtmlEntities } from './utils' import { useNuxtApp } from '#app/nuxt' import { useRequestEvent } from '#app/composables/ssr' @@ -46,8 +48,7 @@ export default defineComponent({ const cHead = ref>>>({ link: [], style: [] }) useHead(cHead) const slotProps = computed(() => { - - return {} + return getSlotProps(html.value) }) function _fetchComponent () { @@ -104,8 +105,8 @@ export default defineComponent({ }, [h(createStaticVNode(html.value, 1))])] if (uid.value) { for (const slot in slots) { - nodes.push(createVNode(Teleport, { to: process.client ? `[nuxt-ssr-component-uid='${uid.value}'] [ssr-slot-name='${slot}']` : `uid=${uid.value};slot=${slot}` }, { - default: () => [slots[slot]?.()] + nodes.push(createVNode(Teleport, { to: process.client ? `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-slot-name='${slot}']` : `uid=${uid.value};slot=${slot}` }, { + default: () => [slots[slot]?.(slotProps.value[slot])] })) } } @@ -154,3 +155,14 @@ function isStartFragment (element: RendererNode) { function isEndFragment (element: RendererNode) { return element.nodeName === '#comment' && element.nodeValue === ']' } +const SLOT_PROPS_RE = /]*nuxt-ssr-slot-name="([^"]*)" nuxt-ssr-slot-data="([^"]*)"[^/|>]*>/g +function getSlotProps (html: string) { + const slotsDivs = html.matchAll(SLOT_PROPS_RE) + const data:Record = {} + for (const slot of slotsDivs) { + const [_, slotName, json] = slot + const slotData = destr(decodeHtmlEntities(json)) + data[slotName] = mergeProps(slotData._default, slotData) + } + return data +} diff --git a/packages/nuxt/src/app/components/utils.ts b/packages/nuxt/src/app/components/utils.ts index 5865558278e5..b6adc69765b5 100644 --- a/packages/nuxt/src/app/components/utils.ts +++ b/packages/nuxt/src/app/components/utils.ts @@ -50,3 +50,21 @@ export function createBuffer () { } } } + +const TRANSLATE_RE = /&(nbsp|amp|quot|lt|gt);/g +const NUMSTR_RE = /&#(\d+);/gi +export function decodeHtmlEntities (html: string) { + const translateDict = { + nbsp: ' ', + amp: '&', + quot: '"', + lt: '<', + gt: '>' + } as const + return html.replace(TRANSLATE_RE, function (_, entity: keyof typeof translateDict) { + return translateDict[entity] + }).replace(NUMSTR_RE, function (_, numStr: string) { + const num = parseInt(numStr, 10) + return String.fromCharCode(num) + }) +} diff --git a/packages/nuxt/src/components/islandsTransform.ts b/packages/nuxt/src/components/islandsTransform.ts index 34ffa3aa3dab..653f4f933cb9 100644 --- a/packages/nuxt/src/components/islandsTransform.ts +++ b/packages/nuxt/src/components/islandsTransform.ts @@ -26,7 +26,7 @@ export const islandsTransform = createUnplugin((options: ServerOnlyComponentTran if (!code.includes(']*)\/?>/g, (_, attrs: string) => { + s.replaceAll(/]*)(\/)?>/g, (_, attrs: string, selfClosing: string) => { let slotName = 'default' const bindings: Record = {} const parsedAttrs = attrs.replaceAll(ATTRS_RE, (matched, name, value) => { @@ -46,8 +46,7 @@ export const islandsTransform = createUnplugin((options: ServerOnlyComponentTran return '' }) const ssrScopeData = getBindings(bindings) - - return `
` + return `
` }) s.replaceAll('', '
') @@ -55,7 +54,6 @@ export const islandsTransform = createUnplugin((options: ServerOnlyComponentTran return { code: s.toString(), map: s.generateMap({ source: id, includeContent: true }) - } } } @@ -70,5 +68,5 @@ function getBindings (bindings: Record): string { if (Object.keys(bindings).length === 0) { return '' } const content = Object.entries(bindings).map(([name, value]) => isBinding(name) ? `${name.slice(1)}: ${value}` : `${name}: \`${value}\``).join(',') - return `:ssr-slot-data="JSON.stringify({ ${content} })"` + return `:nuxt-ssr-slot-data="JSON.stringify({ ${content} })"` } diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index be2532266643..6e469fb78c52 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -457,7 +457,7 @@ function replaceServerOnlyComponentsSlots (ssrContext: NuxtSSRContext, html: str if (!match) { continue } const [, uid, slot] = match if (!uid || !slot) { continue } - html = html.replace(new RegExp(`
((?!ssr-slot-name="${slot}"|nuxt-ssr-component-uid).)*
]*)>`), (full) => { + html = html.replace(new RegExp(`
((?!nuxt-ssr-slot-name="${slot}"|nuxt-ssr-component-uid).)*
]*)>`), (full) => { return full + teleports[key] }) } diff --git a/test/fixtures/basic/pages/islands.vue b/test/fixtures/basic/pages/islands.vue index 083d6b3423fd..85a9ce38ebc0 100644 --- a/test/fixtures/basic/pages/islands.vue +++ b/test/fixtures/basic/pages/islands.vue @@ -45,9 +45,9 @@ const count = ref(0)
- @@ -17,6 +18,5 @@ defineProps<{ count: number }>() - const { data } = await useFetch('/api/very-long-request') diff --git a/test/fixtures/basic/pages/islands.vue b/test/fixtures/basic/pages/islands.vue index 85a9ce38ebc0..722edde550be 100644 --- a/test/fixtures/basic/pages/islands.vue +++ b/test/fixtures/basic/pages/islands.vue @@ -50,6 +50,11 @@ const count = ref(0) Slot with name test - scoped data {{ scoped }}
+