sveltejs / kit

web development, streamlined
https://svelte.dev/docs/kit
MIT License
18.77k stars 1.96k forks source link

`<svelte:head>` duplicate tags when using `+layout.svelte` #10089

Open darbymanning opened 1 year ago

darbymanning commented 1 year ago

Describe the bug

This is similar to https://github.com/sveltejs/kit/issues/6858, https://github.com/sveltejs/svelte/issues/4533, https://github.com/sveltejs/svelte/issues/6463, https://github.com/sveltejs/svelte/issues/7444 but is SvelteKit specific.

When using <svelte:head> in +layout.svelte, some tags are duplicated when then using <svelte:head> on other pages. It looks like <title> is de-duped successfully, but other meta tags slip through, giving duplicates.

This is a problem for me when working with Opengraph tags - my hope was that the last tag attributed would just be picked up when sharing a link, but that doesn't seem to happen, and it's always picking up the first meta tag it finds instead. Since SvelteKit already elegantly handles duplicate <title> tags it feels like this is a bug, and that it should also account for duplicate <meta> tags too.

Potential work around here of course is just to define <svelte:head> in each individual page file, but this isn't ideal DX.

Reproduction

https://www.sveltelab.dev/eq6abubatgq8jn1

Logs

No response

System Info

System:
    OS: macOS 13.3.1
    CPU: (8) arm64 Apple M1 Pro
    Memory: 103.92 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.12.1 - ~/.nvm/versions/node/v18.12.1/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v18.12.1/bin/yarn
    npm: 8.19.2 - ~/.nvm/versions/node/v18.12.1/bin/npm
  Browsers:
    Brave Browser: 113.1.51.110
    Chrome: 113.0.5672.126
    Safari: 16.4
  npmPackages:
    @sveltejs/adapter-auto: ^2.1.0 => 2.1.0 
    @sveltejs/kit: ^1.20.1 => 1.20.1 
    svelte: ^3.59.1 => 3.59.1 
    vite: ^4.3.9 => 4.3.9

Severity

annoyance

Additional Information

No response

ghostdevv commented 1 year ago

Related: #1540

You can take a look here in the docs, which is the easiest solution atm iirc

dummdidumm commented 1 year ago

We can't solve this within Svelte itself, because each component renders itself "in isolation" and doesn't know about the head of others. So we'd need to check in SvelteKit that no tags are complete duplicates, i.e. same attributes - though are there tags in head where it's valid to have them completely the same besides their values, does anyone know? Doing such a filter is probably no easy task since we'd essentially need a mini html parser and it would run on each response, which should be carefully weighed against the potentially bad performance impact.

tejas-crabnebula commented 1 year ago

Just dropping in here to mention that this issue still exists and is affecting us. I'd love to help find a solution to this.

ibrahimqasim-abtrace commented 1 year ago

We can't solve this within Svelte itself, because each component renders itself "in isolation" and doesn't know about the head of others. So we'd need to check in SvelteKit that no tags are complete duplicates, i.e. same attributes - though are there tags in head where it's valid to have them completely the same besides their values, does anyone know? Doing such a filter is probably no easy task since we'd essentially need a mini html parser and it would run on each response, which should be carefully weighed against the potentially bad performance impact.

Shouldn't components be aware of what they have included in <svelte:head>? E.g. I would expect the following to work:

// HeadComponents.svelte

<title>
  <slot />
</title>
// HeadWrapper.svelte
<svelte:head>
  <HeadWrapper>
    <slot />
  </HeadWrapper>
</svelte:head>
// a/+page.svelte
<HeadWrapper>
   A Title
</HeadWrapper>
// b/+page.svelte
<HeadWrapper>
   B Title
</HeadWrapper>

I would expect page a to show title A Title and b to show B Title (or other head tags as needed). But what happens is that the tags from a do not get unmounted when switching pages.

ctigrisht commented 1 year ago

this issue is also impacting me, some pages seem to have dual description and keywords, but not a <title>, I'd like this fixed also

coyotte508 commented 1 year ago

You can use the $page store in +layout.svelte, including $page.data.

So you can return the keywords in your page's load function, and in +layout.svelte check for $page.data.keywords:

<svelte:head>
  {#if $page.data.keywords}
    <meta ...>
  {:else}
    <meta ....>
  {/if}
</svelte:head>

As a workaround