Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

Commit

Permalink
fix(nuxt): don't treeshake client-only fallback templates (#7659)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed Sep 20, 2022
1 parent 42cf48e commit f8a2356
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 4 deletions.
12 changes: 8 additions & 4 deletions packages/nuxt/src/components/tree-shake.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { Component } from '@nuxt/schema'

interface TreeShakeTemplatePluginOptions {
sourcemap?: boolean
getComponents(): Component[]
getComponents (): Component[]
}

export const TreeShakeTemplatePlugin = createUnplugin((options: TreeShakeTemplatePluginOptions) => {
Expand All @@ -26,16 +26,20 @@ export const TreeShakeTemplatePlugin = createUnplugin((options: TreeShakeTemplat
.filter(c => c.mode === 'client' && !components.some(other => other.mode !== 'client' && other.pascalName === c.pascalName))
.map(c => `${c.pascalName}|${c.kebabName}`)
.concat('ClientOnly|client-only')
.map(component => `<(${component})[^>]*>[\\s\\S]*?<\\/(${component})>`)
.map(component => `<(${component})(| [^>]*)>[\\s\\S]*?<\\/(${component})>`)

regexpMap.set(components, new RegExp(`(${clientOnlyComponents.join('|')})`, 'g'))
}

const COMPONENTS_RE = regexpMap.get(components)!
const s = new MagicString(code)

// Do not render client-only slots on SSR, but preserve attributes
s.replace(COMPONENTS_RE, r => r.replace(/<([^>]*[^/])\/?>[\s\S]*$/, '<$1 />'))
// Do not render client-only slots on SSR, but preserve attributes and fallback/placeholder slots
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()) {
return {
Expand Down
2 changes: 2 additions & 0 deletions test/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ describe('pages', () => {
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-setup" foo="hello">')
expect(html).toContain('<div>Fallback</div>')
expect(html).not.toContain('Should not be server rendered')

await expectNoClientErrors('/client-only-components')
})
Expand Down
6 changes: 6 additions & 0 deletions test/fixtures/basic/pages/client-only-components.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,11 @@
</div>
</template>
</ClientOnlySetupScript>
<ClientOnly>
Should not be server rendered.
<template #fallback>
<div>Fallback</div>
</template>
</ClientOnly>
</div>
</template>

0 comments on commit f8a2356

Please sign in to comment.