feat(nuxt): allow fallback production content in `<DevOnly>` (#20817)

This commit is contained in:
Inesh Bose 2023-05-13 23:32:31 +01:00 committed by GitHub
parent 900ee6dc8b
commit d077c10c41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 18 additions and 3 deletions

View File

@ -336,6 +336,11 @@ The content will not be included in production builds and tree-shaken.
<DevOnly>
<!-- this component will only be rendered during development -->
<LazyDebugBar />
<!-- if you ever require to have a replacement during production -->
<template #fallback>
<div><!-- empty div for flex.justify-between --></div>
</template>
</DevOnly>
</div>
</template>

View File

@ -6,6 +6,6 @@ export default defineComponent({
if (process.dev) {
return () => props.slots.default?.()
}
return () => null
return () => props.slots.fallback?.()
}
})

View File

@ -9,7 +9,7 @@ interface DevOnlyPluginOptions {
}
export const DevOnlyPlugin = createUnplugin((options: DevOnlyPluginOptions) => {
const DEVONLY_COMP_RE = /<(dev-only|DevOnly)>[\s\S]*?<\/(dev-only|DevOnly)>/g
const DEVONLY_COMP_RE = /<(?:dev-only|DevOnly)>[^<]*(?:<template\s+#fallback>(?<fallback>[\s\S]*?)<\/template>)?[\s\S]*?<\/(?:dev-only|DevOnly)>/g
return {
name: 'nuxt:server-devonly:transform',
@ -29,7 +29,7 @@ export const DevOnlyPlugin = createUnplugin((options: DevOnlyPluginOptions) => {
const s = new MagicString(code)
const strippedCode = stripLiteral(code)
for (const match of strippedCode.matchAll(DEVONLY_COMP_RE) || []) {
s.remove(match.index!, match.index! + match[0].length)
s.overwrite(match.index!, match.index! + match[0].length, match.groups?.fallback || '')
}
if (s.hasChanged()) {

View File

@ -83,6 +83,8 @@ describe('pages', () => {
expect(html).toContain('Composable | star: auto imported from ~/composables/nested/bar.ts via star export')
// should import components
expect(html).toContain('This is a custom component with a named export.')
// should remove dev-only and replace with any fallback content
expect(html).toContain(isDev() ? 'Some dev-only info' : 'Some prod-only info')
// should apply attributes to client-only components
expect(html).toContain('<div style="color:red;" class="client-only"></div>')
// should render server-only components

View File

@ -11,6 +11,14 @@
<div>Composable | star: {{ useNestedBar() }}</div>
<DevOnly>Some dev-only info</DevOnly>
<div><DevOnly>Some dev-only info</DevOnly></div>
<div>
<DevOnly>
Some dev-only info
<template #fallback>
Some prod-only info
</template>
</DevOnly>
</div>
<div>Path: {{ $route.fullPath }}</div>
<NuxtLink to="/">
Link