-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(remix-react): support Open Graph "verticals" in meta
function
#2497
Conversation
This PR #2331 extends the meta function to allow for object syntax. export function meta() {
return {
// Special cases
title: 'My title', // <title>My title</title>
charset: "utf-8", // <meta charset="utf-8" />
"og:xxx": "url", // <meta property="og:xxx" content="url" />
// content => name
description: 'My description', // <meta name="description" content="My description" />
"twitter:card": "body", // twitter uses content and name, so I can do that
// <meta {...value} />
"fb:app_id": { property: 'fb:app_id', content: '1234' }, // <meta property="fb:app_id" content="1234" />
"refresh": { httpEquiv: 'refresh', content: '3;url=https://www.mozilla.org' }, // <meta http-equiv="refresh" content="3;url=https://www.mozilla.org" />
}
} So you'll be able to do this. Remix simply spreads the object into a new meta element. "article:published_type": { property: "article:published_type", content: "..." } This way Remix will no longer need to special case property names. |
You can never remove I don't see that #2331 negates this PR at all. |
And why should a user suddenly need to know that Open Graph uses "property" instead of "name"? They didn't before. With my fix, this just works: export function meta() {
return {
"og:type": "article",
"article:published_time": "2022-03-25T00:00:00.000Z"
}
} Without it (and with #2331) they need to jump through hoops: export function meta() {
return {
"og:type": "article",
"article:published_time": { property: "article:published_time", content: "2022-03-25T00:00:00.000Z" }
}
} I love the fact that #2331 adds so much flexibility (and it should definitely be part of remix ASAP), but what a hack compared to my fix. "article:published_time" defined twice? That should have been a red flag right there. IMO, both PRs should be merged. |
If I were part of the discussion on #2331, I would have liked to see this for your last two examples: "property": { // define one or more elements that use "property" vs "name"
'fb:app_id', '1234' // <meta property="fb:app_id" content="1234" />
'foo', 'bar' // <meta property="foo" content="bar" />
},
"httpEquiv": { // define one or more elements that use "httpEquiv" vs "name"
'refresh', '3;url=https://www.mozilla.org' // <meta http-equiv="refresh" content="3;url=https://www.mozilla.org" />
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree on merging this one, the code is really simple, and between just using the meta tag of OG verticals and the other approach using objects this is way simpler.
I believe the issue they were trying to solve is to eliminate the need for all these special cases. Would have been nice if the HTML spec simply said any key that includes ":" should use
They would have to do
Unfortunately the object syntax requires a unique key. Remix doesn't care about the key name if you're using the object syntax, so you could name it anything. "property": {
'fb:app_id', '1234' // <meta property="fb:app_id" content="1234" />
'foo', 'bar' // <meta property="foo" content="bar" />
},
"httpEquiv": {
'refresh', '3;url=https://www.mozilla.org' // <meta http-equiv="refresh" content="3;url=https://www.mozilla.org" />
}, Hmm.. this makes export const meta = () => [
{ title: 'my title' },
{ charset: "utf-8" },
{ property: "og:xxx", content: "url" },
{ property: "article:published_time", content: "..." },
{ name: "description", content: "..." },
{ name: "twitter:card", content: "..." },
{ property: "fb:app_id", content: "..." },
{ httpEquiv: "refresh", content: "..." },
...
] |
There's no reason that |
Yeah, I think they'd accept a PR for an array version of I think this should be the preferred method going forward and deprecate the object syntax. |
Not true. They can't remove |
I meant for the array version. Sorry for not being clear. |
If I had my druthers, they would revert #2331 (as it hasn't shipped), add support for arrays, and merge this PR, though I doubt I will get my druthers. |
Something like this const metaValues = route.meta({data: route.loaderData))
if (Array.isArray(metaValues)) {
return metaValues.map(entry => {
if (entry.hasOwnProperty('title')) {
return <title>{entry.title}</title>
} else {
return <meta {...entry}/>
}
})
} |
a quick code review... ;) You should allow const metaValues = route.meta({ data: route.loaderData });
if (Array.isArray(metaValues)) {
return metaValues.map((entry) =>
entry.hasOwnProperty("title") && Object.keys(entry).length == 1 ? (
<title>{entry.title}</title>
) : (
<meta {...entry} />
)
);
} |
Ha, well not bad for browser code. |
oops! we forgot |
Meta
component
Meta
componentmeta
function
@MichaelDeBoey done |
I wish I had seen #2331 before it got merged. Please remember not to merge things that change the public API without the approval from me or @mjackson. When I first made As we've seen a handful of adjustments to our one-offs for meta, I've been expecting to add the ability to return an array and just render it like we do export function meta() {
return [
{ title: "okay, still one off" }, // 👈 still need one weirdo w/ arrays though
{ beef: "who cares", content: "not remix" }
// <meta beef="who cares" content="not remix" />
]
] I'd actually like to
@donavon you up for it? 🙏 |
Also note, it's not as simple as We'll need to still do a "merge" where the child meta wins. We can't have two of the same meta tags: 🚫
<title>parent</title>
<title>child</title>
<meta name="description" content="parent" />
<meta name="description" content="child" /> |
I'm good with not accepting this PR and reverting object syntax in lieu of an array PR and understand on needing to "merge". But what would you use as a "key" when you merged? |
I dunno, that's probably why I used an object in the first place 😂 |
of source, technically, you would need to bump the major version as object syntax is out there. |
playing devil's advocate for a second, a merge |
Like the 10 second rule when food falls on the floor, semver has a 10 day rule 😜 |
If you can't figure out a good key, another way around this is to only use meta from the leaf route and warn when meta is used in a layout route. That way there is no merge. Only the leaf route gets to add meta to avoid the problem altogether (this includes index routes) |
This would mean we would break having |
Just spitballing here... if a property called else if function warn() { console.warn("no key found, you should set a key") }
const { name, property, title, key=name ?? property ?? title ?? warn()} = obj;
if (key) //merge here |
BTW: I'm working on the Array version of I'm converting the special-case props to the array version, so the |
Ok, I have a draft PR #2598. I've added tests, but for some reason, I can't get the integration tests to run (even on a clean build, I get errors). I have stand-alone test that shows that it properly handles both object-syntax and array-syntax with correct overrides. I will update the documentation after the initial review. |
Closing this since we have the new meta API since 1.8.0 |
According to the Open Graph spec you can have "verticals" that have a prefix other than
og:
. These verticals have a prefix that matches the value specified inog:type
up until the first period.For example, there is a vertical of "music". Within "music" you can have an
og:type
of "music.song".When you specify
og:type
of "music.song" you can now have additional meta elements that are prefixed withmusic:
(notog:
) that must also use "property" instead of "name".For example, this is valid:
But currently, Remix renders the two "music" metas as
name
.This PR will fix this.
Production issue
I have a real-life example of this bug. My blogging engine uses an
og:type
of "article" and erroneously renders this in production. (see https://donavon.com/blog/remix-locale)NOTE: I've patched
components.js
so I no longer have this issue in prod.With this PR, it will render correctly as: