mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
fix(nuxt): don't treeshake client-only fallback templates (#7659)
This commit is contained in:
parent
42cf48e45d
commit
f8a23564c3
@ -6,7 +6,7 @@ import type { Component } from '@nuxt/schema'
|
|||||||
|
|
||||||
interface TreeShakeTemplatePluginOptions {
|
interface TreeShakeTemplatePluginOptions {
|
||||||
sourcemap?: boolean
|
sourcemap?: boolean
|
||||||
getComponents(): Component[]
|
getComponents (): Component[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TreeShakeTemplatePlugin = createUnplugin((options: TreeShakeTemplatePluginOptions) => {
|
export const TreeShakeTemplatePlugin = createUnplugin((options: TreeShakeTemplatePluginOptions) => {
|
||||||
@ -26,7 +26,7 @@ export const TreeShakeTemplatePlugin = createUnplugin((options: TreeShakeTemplat
|
|||||||
.filter(c => c.mode === 'client' && !components.some(other => other.mode !== 'client' && other.pascalName === c.pascalName))
|
.filter(c => c.mode === 'client' && !components.some(other => other.mode !== 'client' && other.pascalName === c.pascalName))
|
||||||
.map(c => `${c.pascalName}|${c.kebabName}`)
|
.map(c => `${c.pascalName}|${c.kebabName}`)
|
||||||
.concat('ClientOnly|client-only')
|
.concat('ClientOnly|client-only')
|
||||||
.map(component => `<(${component})[^>]*>[\\s\\S]*?<\\/(${component})>`)
|
.map(component => `<(${component})(| [^>]*)>[\\s\\S]*?<\\/(${component})>`)
|
||||||
|
|
||||||
regexpMap.set(components, new RegExp(`(${clientOnlyComponents.join('|')})`, 'g'))
|
regexpMap.set(components, new RegExp(`(${clientOnlyComponents.join('|')})`, 'g'))
|
||||||
}
|
}
|
||||||
@ -34,8 +34,12 @@ export const TreeShakeTemplatePlugin = createUnplugin((options: TreeShakeTemplat
|
|||||||
const COMPONENTS_RE = regexpMap.get(components)!
|
const COMPONENTS_RE = regexpMap.get(components)!
|
||||||
const s = new MagicString(code)
|
const s = new MagicString(code)
|
||||||
|
|
||||||
// Do not render client-only slots on SSR, but preserve attributes
|
// Do not render client-only slots on SSR, but preserve attributes and fallback/placeholder slots
|
||||||
s.replace(COMPONENTS_RE, r => r.replace(/<([^>]*[^/])\/?>[\s\S]*$/, '<$1 />'))
|
s.replace(COMPONENTS_RE, r => r.replace(/<([^>]*[^/])\/?>[\s\S]*$/, (chunk: string, el: string) => {
|
||||||
|
const fallback = chunk.match(/<template[^>]*(#|v-slot:)(fallback|placeholder)[^>]*>[\s\S]*?<\/template>/)?.[0] || ''
|
||||||
|
const tag = el.split(' ').shift()
|
||||||
|
return `<${el}>${fallback}</${tag}>`
|
||||||
|
}))
|
||||||
|
|
||||||
if (s.hasChanged()) {
|
if (s.hasChanged()) {
|
||||||
return {
|
return {
|
||||||
|
@ -137,6 +137,8 @@ describe('pages', () => {
|
|||||||
const html = await $fetch('/client-only-components')
|
const html = await $fetch('/client-only-components')
|
||||||
expect(html).toContain('<div class="client-only-script" foo="bar">')
|
expect(html).toContain('<div class="client-only-script" foo="bar">')
|
||||||
expect(html).toContain('<div class="client-only-script-setup" foo="hello">')
|
expect(html).toContain('<div class="client-only-script-setup" foo="hello">')
|
||||||
|
expect(html).toContain('<div>Fallback</div>')
|
||||||
|
expect(html).not.toContain('Should not be server rendered')
|
||||||
|
|
||||||
await expectNoClientErrors('/client-only-components')
|
await expectNoClientErrors('/client-only-components')
|
||||||
})
|
})
|
||||||
|
@ -8,5 +8,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ClientOnlySetupScript>
|
</ClientOnlySetupScript>
|
||||||
|
<ClientOnly>
|
||||||
|
Should not be server rendered.
|
||||||
|
<template #fallback>
|
||||||
|
<div>Fallback</div>
|
||||||
|
</template>
|
||||||
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user