Skip to content

Commit

Permalink
feat(start): move scripts,links, and meta to the head (#2571)
Browse files Browse the repository at this point in the history
This minor is non-breaking for Router users, since it's undocumented to the public API, but **is breaking** for Start alpha users. 

This changes the options signature for meta from this:
```tsx
createRoute({
  meta: () => [
    ...
  ],
  links: () => [
    ...
  ],
})
```

to this:

```tsx
createRoute({
  head: () => ({
    meta: [
      ...
    ],
    links: [
      ...
    ],
  })
})
```
  • Loading branch information
SeanCassiere authored Nov 17, 2024
1 parent acd33f7 commit 4ae6ca9
Show file tree
Hide file tree
Showing 118 changed files with 1,009 additions and 916 deletions.
26 changes: 14 additions & 12 deletions docs/framework/react/start/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,18 +199,20 @@ import { Meta, Scripts } from '@tanstack/start'
import type { ReactNode } from 'react'

export const Route = createRootRoute({
meta: () => [
{
charSet: 'utf-8',
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1',
},
{
title: 'TanStack Start Starter',
},
],
head: () => ({
meta: [
{
charSet: 'utf-8',
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1',
},
{
title: 'TanStack Start Starter',
},
],
}),
component: RootComponent,
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { ErrorComponentProps } from '@tanstack/react-router'

export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => fetchPost(postId),
errorComponent: PostErrorComponent as any,
errorComponent: PostErrorComponent,
notFoundComponent: () => {
return <p>Post not found</p>
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { ErrorComponentProps } from '@tanstack/react-router'

export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => fetchPost(postId),
errorComponent: PostErrorComponent as any,
errorComponent: PostErrorComponent,
notFoundComponent: () => {
return <p>Post not found</p>
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const Route = createFileRoute('/posts/$postId')({
component: PostComponent,
})

export function PostErrorComponent({ error, reset }: ErrorComponentProps) {
export function PostErrorComponent({ error }: ErrorComponentProps) {
const router = useRouter()
if (error instanceof PostNotFoundError) {
return <div>{error.message}</div>
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-router/basic-react-query/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from 'react'
import ReactDOM from 'react-dom/client'
import {
ErrorComponent,
type ErrorComponentProps,
Link,
Outlet,
RouterProvider,
Expand All @@ -20,6 +19,7 @@ import {
useSuspenseQuery,
} from '@tanstack/react-query'
import { NotFoundError, postQueryOptions, postsQueryOptions } from './posts'
import type { ErrorComponentProps } from '@tanstack/react-router'

const rootRoute = createRootRouteWithContext<{
queryClient: QueryClient
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-router/basic-scroll-restoration/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ const router = createRouter({ routeTree, defaultPreload: 'intent' })

declare global {
interface Window {
invokeOrders: string[]
invokeOrders: Array<string>
}
}
window.invokeOrders = []
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Link, createFileRoute } from '@tanstack/react-router'
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/classic/hello/')({
component: () => <div>This is the index</div>,
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-router/basic/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import ReactDOM from 'react-dom/client'
import {
ErrorComponent,
type ErrorComponentProps,
Link,
Outlet,
RouterProvider,
Expand All @@ -11,6 +10,7 @@ import {
} from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
import { NotFoundError, fetchPost, fetchPosts } from './posts'
import type { ErrorComponentProps } from '@tanstack/react-router'

const rootRoute = createRootRoute({
component: RootComponent,
Expand Down
1 change: 1 addition & 0 deletions e2e/start/basic-auth/app/client.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// <reference types="vinxi/types/client" />
import { hydrateRoot } from 'react-dom/client'
import { StartClient } from '@tanstack/start'
import { createRouter } from './router'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {
ErrorComponent,
ErrorComponentProps,
Link,
rootRouteId,
useMatch,
useRouter,
} from '@tanstack/react-router'
import type { ErrorComponentProps } from '@tanstack/react-router'

export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
const router = useRouter()
Expand Down
75 changes: 39 additions & 36 deletions e2e/start/basic-auth/app/routes/__root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
import { Meta, Scripts, createServerFn } from '@tanstack/start'
import * as React from 'react'

import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js'
import { NotFound } from '~/components/NotFound.js'
import appCss from '~/styles/app.css?url'
Expand All @@ -27,42 +28,44 @@ const fetchUser = createServerFn({ method: 'GET' }).handler(async () => {
})

export const Route = createRootRoute({
meta: () => [
{
charSet: 'utf-8',
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1',
},
...seo({
title:
'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework',
description: `TanStack Start is a type-safe, client-first, full-stack React framework. `,
}),
],
links: () => [
{ rel: 'stylesheet', href: appCss },
{
rel: 'apple-touch-icon',
sizes: '180x180',
href: '/apple-touch-icon.png',
},
{
rel: 'icon',
type: 'image/png',
sizes: '32x32',
href: '/favicon-32x32.png',
},
{
rel: 'icon',
type: 'image/png',
sizes: '16x16',
href: '/favicon-16x16.png',
},
{ rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
{ rel: 'icon', href: '/favicon.ico' },
],
head: () => ({
meta: [
{
charSet: 'utf-8',
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1',
},
...seo({
title:
'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework',
description: `TanStack Start is a type-safe, client-first, full-stack React framework. `,
}),
],
links: [
{ rel: 'stylesheet', href: appCss },
{
rel: 'apple-touch-icon',
sizes: '180x180',
href: '/apple-touch-icon.png',
},
{
rel: 'icon',
type: 'image/png',
sizes: '32x32',
href: '/favicon-32x32.png',
},
{
rel: 'icon',
type: 'image/png',
sizes: '16x16',
href: '/favicon-16x16.png',
},
{ rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
{ rel: 'icon', href: '/favicon.ico' },
],
}),
beforeLoad: async () => {
const user = await fetchUser()

Expand Down
1 change: 1 addition & 0 deletions e2e/start/basic-auth/app/routes/_authed.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/start'

import { hashPassword, prismaClient } from '~/utils/prisma'
import { Login } from '~/components/Login'
import { useAppSession } from '~/utils/session'
Expand Down
3 changes: 2 additions & 1 deletion e2e/start/basic-auth/app/routes/_authed/posts.$postId.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { ErrorComponent, createFileRoute } from '@tanstack/react-router'
import type { ErrorComponentProps } from '@tanstack/react-router'

import { NotFound } from '~/components/NotFound.js'
import { fetchPost } from '~/utils/posts.js'

export const Route = createFileRoute('/_authed/posts/$postId')({
loader: ({ params: { postId } }) => fetchPost({ data: postId }),
errorComponent: PostErrorComponent as any,
errorComponent: PostErrorComponent,
component: PostComponent,
notFoundComponent: () => {
return <NotFound>Post not found</NotFound>
Expand Down
1 change: 1 addition & 0 deletions e2e/start/basic-auth/app/routes/_authed/posts.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Link, Outlet, createFileRoute } from '@tanstack/react-router'

import { fetchPosts } from '~/utils/posts.js'

export const Route = createFileRoute('/_authed/posts')({
Expand Down
1 change: 1 addition & 0 deletions e2e/start/basic-auth/app/routes/login.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createFileRoute } from '@tanstack/react-router'

import { Login } from '~/components/Login'

export const Route = createFileRoute('/login')({
Expand Down
1 change: 1 addition & 0 deletions e2e/start/basic-auth/app/routes/logout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createFileRoute, redirect } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/start'

import { useAppSession } from '~/utils/session'

const logoutFn = createServerFn({ method: 'POST' }).handler(async () => {
Expand Down
1 change: 1 addition & 0 deletions e2e/start/basic-react-query/app/client.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// <reference types="vinxi/types/client" />
import { hydrateRoot } from 'react-dom/client'
import { StartClient } from '@tanstack/start'
import { createRouter } from './router'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {
ErrorComponent,
ErrorComponentProps,
Link,
rootRouteId,
useMatch,
useRouter,
} from '@tanstack/react-router'
import type { ErrorComponentProps } from '@tanstack/react-router'

export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
const router = useRouter()
Expand Down
75 changes: 38 additions & 37 deletions e2e/start/basic-react-query/app/routes/__root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,50 @@ import * as React from 'react'
import type { QueryClient } from '@tanstack/react-query'
import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary'
import { NotFound } from '~/components/NotFound'
// @ts-expect-error
import appCss from '~/styles/app.css?url'
import { seo } from '~/utils/seo'

export const Route = createRootRouteWithContext<{
queryClient: QueryClient
}>()({
meta: () => [
{
charSet: 'utf-8',
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1',
},
...seo({
title:
'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework',
description: `TanStack Start is a type-safe, client-first, full-stack React framework. `,
}),
],
links: () => [
{ rel: 'stylesheet', href: appCss },
{
rel: 'apple-touch-icon',
sizes: '180x180',
href: '/apple-touch-icon.png',
},
{
rel: 'icon',
type: 'image/png',
sizes: '32x32',
href: '/favicon-32x32.png',
},
{
rel: 'icon',
type: 'image/png',
sizes: '16x16',
href: '/favicon-16x16.png',
},
{ rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
{ rel: 'icon', href: '/favicon.ico' },
],
head: () => ({
meta: [
{
charSet: 'utf-8',
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1',
},
...seo({
title:
'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework',
description: `TanStack Start is a type-safe, client-first, full-stack React framework. `,
}),
],
links: [
{ rel: 'stylesheet', href: appCss },
{
rel: 'apple-touch-icon',
sizes: '180x180',
href: '/apple-touch-icon.png',
},
{
rel: 'icon',
type: 'image/png',
sizes: '32x32',
href: '/favicon-32x32.png',
},
{
rel: 'icon',
type: 'image/png',
sizes: '16x16',
href: '/favicon-16x16.png',
},
{ rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
{ rel: 'icon', href: '/favicon.ico' },
],
}),
errorComponent: (props) => {
return (
<RootDocument>
Expand Down
13 changes: 6 additions & 7 deletions e2e/start/basic-react-query/app/routes/posts.$postId.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router'
import { useSuspenseQuery } from '@tanstack/react-query'
import { postQueryOptions } from '../utils/posts'
import type { ErrorComponentProps } from '@tanstack/react-router'

import { postQueryOptions } from '~/utils/posts'
import { NotFound } from '~/components/NotFound'

export const Route = createFileRoute('/posts/$postId')({
Expand All @@ -14,12 +15,10 @@ export const Route = createFileRoute('/posts/$postId')({
title: data.title,
}
},
meta: ({ loaderData }) => [
{
title: loaderData.title,
},
],
errorComponent: PostErrorComponent as any,
head: ({ loaderData }) => ({
meta: loaderData ? [{ title: loaderData.title }] : undefined,
}),
errorComponent: PostErrorComponent,
notFoundComponent: () => {
return <NotFound>Post not found</NotFound>
},
Expand Down
Loading

0 comments on commit 4ae6ca9

Please sign in to comment.