S
SolidJSā€¢4w ago
hannus

Duplicate `<link rel="canonical">` in SolidStart

In my SolidStart project, I have the following code:
<Title>Home | Example</Title>
<Link rel="canonical" href="https://www.example.com/" />
<Meta
name="description"
content="something"
/>
<Title>Home | Example</Title>
<Link rel="canonical" href="https://www.example.com/" />
<Meta
name="description"
content="something"
/>
However, in the rendered output, there are two <link rel="canonical"> tags:
<link data-sm="00000000100000100000000800030" rel="canonical" href="https://www.example.com/">
<link rel="canonical" href="https://www.example.com/">
<link data-sm="00000000100000100000000800030" rel="canonical" href="https://www.example.com/">
<link rel="canonical" href="https://www.example.com/">
I tried removing the <Link> tag from the code, and after rendering, there was no canonical link at all. This confirms that the <Link> tag I added is the sole reason for the canonical link appearing.
So, what is causing the duplication of the <link rel="canonical"> tag in the rendered output, and how can I fix it? Or it dose not matter thanks a lot
15 Replies
Jason.json
Jason.jsonā€¢4w ago
Do you use the meta tags inside a <MetaProvider>? I am not sure, but maybe it would solve your issue. MetaProvider example:
import { Meta, Link, MetaProvider } from "@solidjs/meta";

export default function MyComponent() {
// your code..
return <MetaProvider>
<Title>Home | Example</Title>
<Link rel="canonical" href="https://www.example.com/" />
<Meta
name="description"
content="something"
/>
</MetaProvider>
}
import { Meta, Link, MetaProvider } from "@solidjs/meta";

export default function MyComponent() {
// your code..
return <MetaProvider>
<Title>Home | Example</Title>
<Link rel="canonical" href="https://www.example.com/" />
<Meta
name="description"
content="something"
/>
</MetaProvider>
}
mdynnl
mdynnlā€¢4w ago
i believe OP is using solid meta. i think a reproduction is likely necessary for further debugging.
Jason.json
Jason.jsonā€¢4w ago
Not 100% sure about that. That's only my suggestion. šŸ˜„
mdynnl
mdynnlā€¢4w ago
yeah, I'm only guessing but solid start basic template includes it by default + data-sm (what solid meta use to mark nodes it handles) made it clear, and solid meta already handles de-duplication so we definitely need a repro
Jason.json
Jason.jsonā€¢4w ago
yeah that's kinda strange behavior It haven't ever happened for me before tbh
hannus
hannusOPā€¢4w ago
yes, I am using solid-meta. Only Link has data-sm property in the page after rendered. If I removed <Link rel="canonical" href="https://www.example.com/" />, everything goes well.
peerreynders
peerreyndersā€¢4w ago
- Created a fresh SolidStart project: TS/basic - Replaced the src/app.tsx with this:
// file: src/app.tsx
import { Link, Meta, MetaProvider, Title } from '@solidjs/meta';
import { Router } from '@solidjs/router';
import { FileRoutes } from '@solidjs/start/router';
import { Suspense } from 'solid-js';
import './app.css';

import type { ParentProps } from 'solid-js';

function Layout(props: ParentProps) {
return (
<MetaProvider>
<Title>Home | Example</Title>
<Link rel="canonical" href="https://www.example.com/" />
<Meta name="description" content="something" />
<a href="/">Index</a>
<a href="/about">About</a>
<Suspense>{props.children}</Suspense>
</MetaProvider>
);
}

export default function App() {
return (
<Router root={Layout}>
<FileRoutes />
</Router>
);
}
// file: src/app.tsx
import { Link, Meta, MetaProvider, Title } from '@solidjs/meta';
import { Router } from '@solidjs/router';
import { FileRoutes } from '@solidjs/start/router';
import { Suspense } from 'solid-js';
import './app.css';

import type { ParentProps } from 'solid-js';

function Layout(props: ParentProps) {
return (
<MetaProvider>
<Title>Home | Example</Title>
<Link rel="canonical" href="https://www.example.com/" />
<Meta name="description" content="something" />
<a href="/">Index</a>
<a href="/about">About</a>
<Suspense>{props.children}</Suspense>
</MetaProvider>
);
}

export default function App() {
return (
<Router root={Layout}>
<FileRoutes />
</Router>
);
}
ā€¦ which results in exactly this (from "view source"):
<link
data-sm="0000000010000010"
rel="canonical"
href="https://www.example.com/"
/>
<meta data-sm="0000000010000020" name="description" content="something" />
<title data-sm="00000000100000500000110">Hello World</title>
<link
data-sm="0000000010000010"
rel="canonical"
href="https://www.example.com/"
/>
<meta data-sm="0000000010000020" name="description" content="something" />
<title data-sm="00000000100000500000110">Hello World</title>
So unfortunately you haven't provided enough information for a reproduction.
mdynnl
mdynnlā€¢4w ago
Just to add, de-duplication is only done for title and meta at the moment so there's actually room for improvement for other tags too if warranted but the initial problem seems to be duplicates caused by one element, where both ssr-ed and csr-ed tags existing at the same time
Trader101
Trader101ā€¢2w ago
thanks for helping showing how to use meta in solidstart app but what about this?
// @refresh reload
import { createHandler, StartServer } from "@solidjs/start/server";

export default createHandler(() => (
<StartServer
document={({ assets, children, scripts }) => (
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
{assets}
</head>
<body>
<div id="app">{children}</div>
{scripts}
</body>
</html>
)}
/>
));
// @refresh reload
import { createHandler, StartServer } from "@solidjs/start/server";

export default createHandler(() => (
<StartServer
document={({ assets, children, scripts }) => (
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
{assets}
</head>
<body>
<div id="app">{children}</div>
{scripts}
</body>
</html>
)}
/>
));
like we have duplicate head?
peerreynders
peerreyndersā€¢2w ago
Meta places its elements inside the existing head but it doesn't handle elements that already exist within it. It only modifies, removes elements that it placed there to begin with.
Trader101
Trader101ā€¢2w ago
So like I keep the head in entry client or move it entirely to app.tsx? Should i move all meta tags to app.tsx And remove the head from that file I showed above
peerreynders
peerreyndersā€¢2w ago
The head stays in src/entry-server.tsx. You just use <Title/>, <Meta />, etc. in your components when they become relevant. The fallbacks (if any) would be specified right under the MetaProvider typically in the src/app.tsx.
Trader101
Trader101ā€¢2w ago
Yeah I get it before you had solid meta built in it was better imo Like now we have <head> and <Head> In two different places
peerreynders
peerreyndersā€¢2w ago
I'm not aware of any <Head /> component.
Trader101
Trader101ā€¢2w ago
Ye sorry I confused with old solid start

Did you find this page helpful?