diff --git a/packages/nuxt/src/components/islandsTransform.ts b/packages/nuxt/src/components/islandsTransform.ts index c6da0fff4e..1cdc89a831 100644 --- a/packages/nuxt/src/components/islandsTransform.ts +++ b/packages/nuxt/src/components/islandsTransform.ts @@ -4,18 +4,23 @@ import { parseURL } from 'ufo' import { createUnplugin } from 'unplugin' import MagicString from 'magic-string' import { ELEMENT_NODE, parse, walk } from 'ultrahtml' +import { isVue } from '../core/utils' interface ServerOnlyComponentTransformPluginOptions { getComponents: () => Component[] } const SCRIPT_RE = /]*>/g +const HAS_SLOT_RE = /([\s\S]*)<\/template>/ export const islandsTransform = createUnplugin((options: ServerOnlyComponentTransformPluginOptions) => { return { name: 'server-only-component-transform', enforce: 'pre', transformInclude (id) { + if (!isVue(id)) { return false } + const components = options.getComponents() const islands = components.filter(component => component.island || (component.mode === 'server' && !components.some(c => c.pascalName === component.pascalName && c.mode === 'client')) @@ -24,9 +29,10 @@ export const islandsTransform = createUnplugin((options: ServerOnlyComponentTran return islands.some(c => c.filePath === pathname) }, async transform (code, id) { - if (!code.includes('([\s\S]*)<\/template>/) + if (!HAS_SLOT_RE.test(code)) { return } + const template = code.match(TEMPLATE_RE) if (!template) { return } + const startingIndex = template.index || 0 const s = new MagicString(code) s.replace(SCRIPT_RE, (full) => { @@ -51,25 +57,25 @@ export const islandsTransform = createUnplugin((options: ServerOnlyComponentTran const bindings = getBindings(attributes, vfor) if (isSelfClosingTag) { - s.overwrite(loc[0].start, loc[0].end, `
`) + s.overwrite(startingIndex + loc[0].start, startingIndex + loc[0].end, `
`) } else { - s.overwrite(loc[0].start, loc[0].end, `
`) - s.overwrite(loc[1].start, loc[1].end, '
') + s.overwrite(startingIndex + loc[0].start, startingIndex + loc[0].end, `
`) + s.overwrite(startingIndex + loc[1].start, startingIndex + loc[1].end, '
') if (children.length > 1) { // need to wrap instead of applying v-for on each child const wrapperTag = `
` - s.appendRight(loc[0].end, `
${wrapperTag}`) - s.appendLeft(loc[1].start, '
') + s.appendRight(startingIndex + loc[0].end, `
${wrapperTag}`) + s.appendLeft(startingIndex + loc[1].start, '
') } else if (children.length === 1) { if (vfor && children[0].type === ELEMENT_NODE) { const { loc, name, attributes, isSelfClosingTag } = children[0] const attrs = Object.entries(attributes).map(([attr, val]) => `${attr}="${val}"`).join(' ') - s.overwrite(loc[0].start, loc[0].end, `<${name} v-for="${vfor[0]} in ${vfor[1]}" ${attrs} ${isSelfClosingTag ? '/' : ''}>`) + s.overwrite(startingIndex + loc[0].start, startingIndex + loc[0].end, `<${name} v-for="${vfor[0]} in ${vfor[1]}" ${attrs} ${isSelfClosingTag ? '/' : ''}>`) } - s.appendRight(loc[0].end, `
`) - s.appendLeft(loc[1].start, '
') + s.appendRight(startingIndex + loc[0].end, `
`) + s.appendLeft(startingIndex + loc[1].start, '
') } } } diff --git a/test/fixtures/basic/components/ServerOnlyComponent.server.vue b/test/fixtures/basic/components/ServerOnlyComponent.server.vue index fc3dc80e47..e0c5945c1e 100644 --- a/test/fixtures/basic/components/ServerOnlyComponent.server.vue +++ b/test/fixtures/basic/components/ServerOnlyComponent.server.vue @@ -1,15 +1,15 @@ - - + +