nuxt / content

The file-based CMS for your Nuxt application, powered by Markdown and Vue components.
https://content.nuxt.com
MIT License
3.11k stars 624 forks source link

duplicated layout when using document driven with multiple layouts #1722

Open Zerro97 opened 1 year ago

Zerro97 commented 1 year ago

Environment

Reproduction

Reproduction Link: Link

Describe the bug

  1. Put NuxtLayout component in app.vue
<template>
  <div>
    <NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
  </div>
</template>
  1. Enable document driven feature in nuxt.config.ts
  2. Create 2 layouts, 1 for default layout, 1 for custom layout
  3. Create 2 markdown file and specify the layouts made in previous step
---
layout: default
---
---
layout: custom
---

When using layout binding as instructed here, instead of replacing the default layout with the custom layout, custom layout is put within the <slot /> of the default layout (so two layouts showing).

Additional context

Might be related to this PR from nuxt/framework.

Logs

No response

Zerro97 commented 1 year ago

Moving <NuxtLayout> in app.vue to each of individual pages (in page directory) solves the problem.

It seems like the layout defined in app.vue is used no matter whether we define the layout in frontmatter of markdown file.

atinux commented 1 year ago

Actually we don't recommend to use the in app.vue until Vue 3 fixes a bug with Suspense and nested elements.

garyo commented 1 year ago

I'm using latest nuxt-content with document-driven, and I just discovered I don't even have an app.vue at all! But everything seems to work OK. Is that expected? Perhaps it's just using the one from @nuxt/content/dist/runtime/app.vue (which just contains <NuxtPage />)?

Zerro97 commented 1 year ago

I actually got curious about the cause of this behavior so I took a look at the source code..


There is injectPage option in nuxt.config, which determines whether to inject document-driven.vue page into existing nuxt pages during pages:extend nuxt hook.

So, this document-driven.vue page is catch-all [slug].vue page and is used for fetching the page data from markdown files (page data is probably set/fetched at defineNuxtPlugin) and pass them to ContentRenderer which then creates HTML page from the content.

document-driven.vue uses <NuxtLayout> within it and document-driven.vue itself is a page that is injected into <NuxtPage> in app.vue. So if we define <NuxtLayout> in app.vue and choose to inject document-driven.vue into the existing pages, there will be 2 layouts showing, one from app.vue and the other from document-driven.vue.

We can choose not to inject document-driven.vue by setting injectPage to false. So in this case, only the layout defined in app.vue will be shown...

linpengteng commented 1 month ago

@atinux @garyo @Zerro97

I don't have app.vue, but I have the same problem.

https://stackblitz.com/edit/github-5hgwqx?file=layouts%2Fcustom.vue,content%2Fabout.md,nuxt.config.ts,content%2Findex.md