solidjs / solid-meta

Write meta tags to the document head
127 stars 16 forks source link

Tags are not replaced, but getting appended #8

Open rrjanbiah opened 2 years ago

rrjanbiah commented 2 years ago

Say, for example, if index.html is having <title> tag already, the new title tag is getting appended.. so, browser is taking the first one (which is used in the index.html).. in turn looks like the module is not working.

As a quick fix, I had to remove the <title> tag from the index.html. But, that's not the correct solution.. as I want somewhat SEO friendly without SSR for the static hosting.

Apologies for my poor English and hope the issue is clear to the author.

ryansolid commented 2 years ago

We can't diff what is outside of our control. SSR does a trick where it replaces by writing an attribute to server generated meta tags. We should document this. But if you add a data-sm="" attribute to any of your meta tags they will be removed when the client hydrates and replaced with what the library generates.

rrjanbiah commented 2 years ago

@ryansolid Thanks for sharing the hidden treasure :-) <title data-sm="">My title</title> worked great to avoid the appending. Feel free to close the issue unless you want to track the documentation part.

andreas-ateles commented 2 years ago

When setting title why not just remove any existing <title> tags? As there should never be more than one of those.

rrjanbiah commented 2 years ago

@andreas-ateles As I mentioned in original message, I need it for static hosting. For example, think about it when using Facebook debugger or Twitter cards. With it, it would also resolve the root/default page's title for all the pages.

outbackStack commented 2 years ago

It appends the head as well if you have your routes like bellow - client side.

import { Routes, Route } from "solid-app-router"
import { MetaProvider, Title } from "solid-meta";

function Home() {
  return (
    <>
      <MetaProvider>
        <Title>Home Page</Title>
      </MetaProvider>
      <div>
        <h1>Home Page</h1>
      </div >
    </>
  );
}

function About() {
  return (
    <>
      <MetaProvider>
        <Title>About Page</Title>
      </MetaProvider>
      <div>
        <h1>About Page</h1>
      </div >
    </>
  );
}

export default function App() {
  return (<>
    <h1>My Site with Lots of Pages</h1>
    <Routes>
      <Route path="/" element={<Home/>} />
      <Route path="/about"  element={< About/>}  />
    </Routes>
  <>)
}

Result:

Screen Shot 2022-06-21 at 12 25 59 pm
ryansolid commented 2 years ago

You have multiple MetaProviders. Each acts independently. Wrap the whole application in a single MetaProvider and it should work fine.

See: https://codesandbox.io/s/solid-meta-reproduction-3r1qgb

outbackStack commented 2 years ago

thanks @ryansolid, it's working now... Loving solid-js so far 😀

nathan-alden-sr commented 1 year ago

Am I missing something? My index.html has <title data-sm="">Hardcoded Title</title>. My app only has a single <MetaProvider> at the top-level. Then, I provide a <Title> but it's still appending to the DOM according to Chrome:

<title data-sm>Hardcoded Title</title>
...
<title>Set by Title component</title>

I'm using the latest versions of solid-js and @solidjs/meta.

The reason I'm doing this is because I deploy my site as static files to GitHub Pages, which will then be indexed by search engines. For that reason I must have a <title> tag present in index.html, but I then want to overwrite it at runtime in the browser per view for better UX.

ryansolid commented 1 year ago

Yeah I thought this might be the case. We used to do something simple and just remove all the existing tags but now we try to upgrade but if the id doesn't match it stays I imagine. We probably need a convention here. I'm going to ask @nksaraf for his opinion as well.

nathan-alden-sr commented 1 year ago

See https://github.com/solidjs/solid-meta/issues/17 for what I think is an improved design that can help mitigate these issues but also provide more flexibility.

AlexTMjugador commented 1 year ago

For client-side rendering, I worked around this behavior, which was undesirable for me due to the reasons stated above, by assigning an ID to the <title> element in the index.html and removing it on my index.tsx file, before calling render(). It's not a pretty solution, and there will be a tiny, unnoticeable time window during which the page won't have a title at all, but it is more SEO-friendly than the alternative.