vercel / next.js

The React Framework
https://nextjs.org
MIT License
125.88k stars 26.86k forks source link

Adding elements to the next/head causes meta-tags to be replicated/duplicated #17085

Open jaybytez opened 4 years ago

jaybytez commented 4 years ago

Bug report

Describe the bug

We have a Layout component that we use the next/head to build out our meta-tags as well as include our css/scripts.

When we include our Tag Manager, it exposed an issue when the Tag Manager injects scripts onto the page, we are seeing meta-tags get duplicated in the view source. When we remove the Tag Manager, the duplicated meta-tags go away.

We realized that the Tag Manager is adding scripts to the head, and when it does this, it appears to tells next/head to

https://github.com/vercel/next.js/discussions/17020 https://github.com/vercel/next.js/issues/9794

To test this out, we checked out the head-elements example, added a custom JS file that the only thing it does within it is create some elements that it adds to the head. And when the adds happen, meta-tags get duplicated. Not all of the tags get duplicated, just the number of tags about = to the number of head adds our script does.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

https://github.com/jaybytez/head-elements

When running this application and view the Inspector (Firefox) or Elements (Chrome), you can see that meta-tags have been duplicated (charset, viewport, author). The number of tags duplicated is relative to how many add to head calls are made in the script.

Expected behavior

I would expect that adding scripts/elements to the head would not cause meta-tags to be recreated/duplicated.

Screenshots

image

System information

Additional context

It is weird that the meta-tags are duplicated based on an n-1 elements added to the head. So if I make 4 add head calls (like in this example), only 3 meta-tags are duplicated. If I do 3 head calls, then 2 are duplicated.

Also, the view source appears to not have duplicates (I just noticed), but the Inspector/Elements shows the duplicates.

timneutkens commented 4 years ago

Can you try next@canary, the head injection/removal was refactored to work in a different way.

jaybytez commented 4 years ago

@timneutkens, upgrading to the next@canary did resolve the duplicate meta-data issue within the head-elements project. We need to update our project for the webpack 5 pieces, but yes, this is great. It does resolve the duplicate issue.

timneutkens commented 4 years ago

Great so this was fixed in https://github.com/vercel/next.js/pull/16758 and this issue can be closed.

jaybytez commented 4 years ago

Duplication issue is resolved, will close.

krikork commented 3 years ago

Still busted in next 10.0.3

benwwalker commented 3 years ago

Having this issue in 10.0.7 too. I have a component with pagination that dynamically adds canonical/next/prev to the header, but by including <Head> in the component I get duplicate meta charset and meta description tags.

jaybytez commented 3 years ago

This issue exists again in versions of 10.0.x.

renedaniel commented 3 years ago

i am having the same issue if i use gtm script in next 10.0.9

GalInvesting commented 3 years ago

happened to me also

jperezlatimes commented 3 years ago

I am experiencing this as well using next 10.0.9. I removed _document.js from my project entirely to eliminate any potential problems with <Head/> from next/document. I'm now only using the <Head/> component from next/head in my page components and I'm still seeing duplication.

Additionally, the behavior changes depending the order of my tags in next/head component. In this scenario, both charset and description meta tags are duplicated:

<Head>
  <meta name="description" content={description}  />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
  <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
  <title>{title}</title>
</Head>

Re-arranged with title first, and I only see a duplicate charset tag.

<Head>
  <title>{title}</title>
  <meta name="description" content={description} />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
  <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
</Head>
devdpontes commented 3 years ago

To avoid the tags duplication you need to add a key property to the elements, with the same value. e.g. <meta name="description" content={description} key="description"/>

I do have an issue with meta tags, but related to not rendering with SSR when using next/head. It's always only on the client.

jperezlatimes commented 3 years ago

Thankns @devdpontes. That suggestion works for the description tag in scenario 1, but it doesn't explain the re-ordering phenomenon or why I have duplicate charset tags.

nicholaschiang commented 3 years ago

I've created this repro using next@10.1.2: https://codesandbox.io/s/laughing-payne-dt1ty?file=/pages/_app.tsx

import { AppProps } from "next/app";
import { GoogleFonts } from "next-google-fonts";
import Head from "next/head";

import "./global.css";

const scriptThatAddsElToHead =
  `var n=document.createElement('script');` +
  `var a=document.getElementsByTagName('script')[0];` +
  `a.parentNode.insertBefore(n,a);`;

export default function App({ Component, pageProps }: AppProps): JSX.Element {
  return (
    <>
      <h1>Custom App</h1>
      <Head>
        <title>Google Fonts Repro</title>
        <script dangerouslySetInnerHTML={{ __html: scriptThatAddsElToHead }} />
      </Head>
      <GoogleFonts href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" />
      <Component {...pageProps} />
    </>
  );
}
jaybytez commented 3 years ago

@timneutkens - this issue was resolved at some point but is a problem in all versions of nextjs 10+. And for us the problem is that there is the i18n issue with trailingSlash redirecting to the default language, this is fixed in a later nextjs 10.x.x version but we can't upgrade because of this issue causing duplicate meta-tags. Is there any ETA if this will be addressed? We are trying to determine if we have to stay on an older version with a hack in our CDN to manage the trailing slash/i18n issue or determine the SEO impacts of having duplicate meta-tags.

jaybytez commented 3 years ago

So for others having this issue, we are seeing this primarily on charset and viewport. Not sure if others are seeing different tags?

While our SEO team said this isn't a huge impact, the problem is not having a 100% confidence that this wouldn't happen to impact title or description which would significantly impact SEO if these were duplicated.

devdpontes commented 3 years ago

Is the viewport tag exactly the same when duplicated? Because next adds a viewport tag by default, so it might be related to that, when trying to add a custom one.

jaybytez commented 3 years ago

@devdpontes, interesting point and I will take a look at that. For us, the problem only manifests itself in an env where we use our Tag Manager. Our lower level environments shows no duplicates, but they show up when the Tag Manager is enabled, its possible because the Tag Manager utilizes doc write for sync integration, potentially this causes a conflict and makes Nextjs fire this off again.

GalInvesting commented 3 years ago

is there any solution for this?

stefanonava77 commented 3 years ago

any updated on this issue?

georgeck commented 3 years ago

I am able to reproduce this in 11.0.0 as well

In _document.js

<head>
 <meta property="og:title" content="foo" key="title" />
</Head>

and in a page

<head>
 <meta property="og:title" content="bar" key="title" />
</Head>

In the rendered page, both these appear

cristicismas commented 1 year ago

Hi, any updates or workarounds on this? I'm able to reproduce the same issue in next 12.1.0.

Fredkiss3 commented 1 year ago

I don't know where i've seen this, but i've heard that if you add the same key to the <Head /> element everywhere you call it to prevent this.

Something like this :

// In _document.js
<Head key='head'>
 <meta property="og:title" content="foo" key="title" />
</Head>

// In a page
<Head  key='head'>
 <meta property="og:title" content="bar" key="title" />
</Head>
cristicismas commented 1 year ago

@Fredkiss3 this didn't work for me, but it looks like the issue has been fixed in NextJS 13.0.0

Enkratia commented 4 weeks ago

Will it be fixed 4 years later? This issue is not resolved: https://github.com/vercel/next.js/issues/26534 or happend again.