Skip to content

Commit

Permalink
Merge branch 'v2' into remove-serverBuildDirectory-config-in-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-ebey committed Mar 16, 2023
2 parents 0b572a3 + 4b6ecaf commit af8251d
Show file tree
Hide file tree
Showing 70 changed files with 293 additions and 1,060 deletions.
49 changes: 49 additions & 0 deletions .changeset/remove-v1-meta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
"remix": major
"@remix-run/cloudflare": major
"@remix-run/deno": major
"@remix-run/dev": major
"@remix-run/eslint-config": major
"@remix-run/node": major
"@remix-run/react": major
"@remix-run/server-runtime": major
"@remix-run/testing": major
---

We have made a few important changes to the route `meta` API as reflected in the v1 implementation when using the `future.v2_meta` config option.

- The `meta` function should no longer return an object, but an array of objects that map to the HTML tag's respective attributes. This provides more flexibility and control over how certain tags are rendered, and the order in which they appear.
- In most cases, `meta` descriptor objects render a `<meta>` tag. There are a few notable exceptions:
- `{ title: "My app" }` will render `<title?>My app</title>`.
- `{ 'script:ld+json': { /* ... */ } }` will render `<script type="application/ld+json">/* ... */</script>`, where the value is serialized to JSON and rendered inside the `<script>` tag.
- `{ tagName: 'link', ...attributes }` will render `<link {...attributes} />`
- This is useful for things like setting canonical URLs. For loading assets, we encourage you to use the `links` export instead.
- It's important to note that `tagName` may only accept `meta` or `link`, so other arbitrary elements will be ignored.
- `<Meta />` will no longer render the `meta` output from the entire route heirarchy. Only the output from the leaf (current) route will be rendered unless that route does not export a `meta` function, im which case the output from the nearest ancestor route with `meta` will be rendered.
- This change comes from user feedback that auto-merging meta made effective SEO difficult to implement. Our goal is to give you as much control as you need over meta tags for each individual route.
- Our suggested approach is to **only export a `meta` function from leaf route modules**. However, if you do want to render a tag from another matched route, `meta` now accepts a `matches` argument for you to merge or override parent route meta as you'd like.
```tsx
export function meta({ matches }) {
return [
// render all ancestor route meta except for title tags
...matches.flatMap((match) => match.meta).filter(match => !('title' in match)),
{ title: "Override the title!" },
];
}
```
- The `parentsData` argument has been removed. If you need to access data from a parent route, you can use `matches` instead.
```tsx
// before
export function meta({ parentsData }) {
return [{ title: parentsData["routes/some-route"].title }];
}
// after
export function meta({ matches }) {
return [
{
title: matches.find((match) => match.id === "routes/some-route").data
.title,
},
];
}
```
5 changes: 5 additions & 0 deletions .changeset/silver-readers-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/dev": major
---

remove `browserBuildDirectory` config
2 changes: 1 addition & 1 deletion docs/api/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ title: Conventions

[Moved →][moved-36]

#### `HtmlMetaDescriptor`
#### `MetaDescriptor`

[Moved →][moved-37]

Expand Down
12 changes: 6 additions & 6 deletions docs/file-conventions/root.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: globalStylesheetUrl }];
};

export const meta: MetaFunction = () => ({
charset: "utf-8",
title: "My Amazing App",
viewport: "width=device-width,initial-scale=1",
});

export default function App() {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>

{/* All meta exports on all routes will go here */}
<Meta />

Expand Down
10 changes: 5 additions & 5 deletions docs/guides/constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export async function loader() {
}

export function meta() {
return { title: "Posts" };
return [{ title: "Posts" }];
}

export default function Posts() {
Expand All @@ -55,7 +55,7 @@ import { useLoaderData } from "@remix-run/react";
import PostsView from "../PostsView";

export function meta() {
return { title: "Posts" };
return [{ title: "Posts" }];
}

export default function Posts() {
Expand Down Expand Up @@ -90,7 +90,7 @@ export async function loader() {
}

export function meta() {
return { title: "Posts" };
return [{ title: "Posts" }];
}

export default function Posts() {
Expand All @@ -110,7 +110,7 @@ import { prisma } from "../db"; //😬
console.log(prisma); //🥶

export function meta() {
return { title: "Posts" };
return [{ title: "Posts" }];
}

export default function Posts() {
Expand All @@ -136,7 +136,7 @@ export async function loader() {
}

export function meta() {
return { title: "Posts" };
return [{ title: "Posts" }];
}

export default function Posts() {
Expand Down
15 changes: 9 additions & 6 deletions docs/guides/mdx.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ MDX routes allow you to define both meta and headers as if they were a code base
```md
---
meta:
title: My First Post
description: Isn't this awesome?
- title: My First Post
- name: description
content: Isn't this awesome?
headers:
Cache-Control: no-cache
---
Expand Down Expand Up @@ -56,8 +57,9 @@ By creating a `app/routes/posts/first-post.mdx` we can start writing a blog post
```mdx
---
meta:
title: My First Post
description: Isn't this just awesome?
- title: My First Post
- name: description
content: Isn't this just awesome?
---

# Example Markdown Post
Expand All @@ -72,8 +74,9 @@ You can even export all the other things in this module that you can in regular
```mdx
---
meta:
title: My First Post
description: Isn't this awesome?
- title: My First Post
- name: description
content: Isn't this awesome?

headers:
Cache-Control: no-cache
Expand Down
30 changes: 5 additions & 25 deletions docs/guides/migrating-react-router-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -552,33 +552,13 @@ If you currently inject `<link />` tags into your page client-side in your exist

Just as a `<link>` is rendered inside your route component and ultimately rendered in your root `<Links />` component, your app may use some injection trickery to render additional components in the document `<head>`. Often this is done to change the document's `<title>` or `<meta>` tags.

Similar to `links`, each route can also export a `meta` function that—you guessed it—returns a value responsible for rendering `<meta>` tags for that route. This is useful because each route often has its own.

The API is slightly different for `meta`. Instead of an array, it returns an object where the keys represent the meta `name` attribute (or `property` in the case of OpenGraph tags) and the value is the `content` attribute. The object can also accept a `title` property that renders a `<title />` component specifically for that route.

```jsx filename=app/routes/about.jsx lines=[1-10]
export function meta() {
return {
title: "About Us",
"og:title": "About Us",
description: "Doin hoodrat stuff with our friends",
"og:description": "Doin hoodrat stuff with our friends",
"og:image:url": "https://remix.run/og-image.png",
"og:image:alt": "Just doin a bunch of hoodrat stuff",
};
}
Similar to `links`, each route can also export a `meta` function that returns values responsible for rendering `<meta>` tags for that route (as well as a few other tags relevant for metadata, such as `<title>`, `<link rel="canonical">` and `<script type="application/ld+json">`).

export default function About() {
return (
<main>
<h1>About us</h1>
<PageContent />
</main>
);
}
```
The behavior for `meta` is slightly different from `links`. Instead of merging values from other `meta` functions in the route hierarchy, **each leaf route is responsible for rendering its own tags**. This is because:

Again—no more weird dances to get meta into your routes from deep in the component tree. Export them at the route level and let the server handle it. ✨
- You often want more fine-grained control over metadata for optimal SEO
- In the case of some tags that follow the [Open Graph protocol](https://ogp.me/), the ordering of some tags impacts their how they are interpreted by crawlers and social media sites, and its it's less predictable for Remix to assume how complex metadata should be merged
- Some tags allow for multiple values while others do not, and Remix shouldn't assume how you want to handle all of those cases

### Updating imports

Expand Down
10 changes: 5 additions & 5 deletions docs/guides/styling.md
Original file line number Diff line number Diff line change
Expand Up @@ -827,15 +827,15 @@ Here's some sample code to show how you might use Styled Components with Remix (
ScrollRestoration,
} from "@remix-run/react";

export const meta: MetaFunction = () => ({
charset: "utf-8",
viewport: "width=device-width,initial-scale=1",
});

export default function App() {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>
<Meta />
<Links />
{typeof document === "undefined"
Expand Down
Loading

0 comments on commit af8251d

Please sign in to comment.