Перейти к содержимому

15. Meta и Links функции

Remix предоставляет функции meta и links для управления метатегами страницы и подключения стилей/ресурсов прямо из маршрутов.

import type { MetaFunction } from "@remix-run/node";
export const meta: MetaFunction = () => {
return [
{ title: "Мой блог — Технические статьи" },
{ name: "description", content: "Статьи о веб-разработке и React" },
{ property: "og:title", content: "Мой блог" },
{ property: "og:type", content: "website" },
{ property: "og:image", content: "https://example.com/og.jpg" },
{ name: "twitter:card", content: "summary_large_image" },
];
};
export async function loader({ params }) {
const post = await getPost(params.slug);
if (!post) throw new Response("Not Found", { status: 404 });
return json({ post });
}
export const meta: MetaFunction<typeof loader> = ({ data }) => {
if (!data) {
return [{ title: "Статья не найдена" }];
}
return [
{ title: data.post.title },
{ name: "description", content: data.post.excerpt },
{ property: "og:title", content: data.post.title },
{ property: "og:description", content: data.post.excerpt },
{ property: "og:image", content: data.post.coverImage },
{ property: "og:url", content: \`https://blog.example.com/\${data.post.slug}\` },
{ name: "twitter:card", content: "summary_large_image" },
];
};
// Дочерний маршрут может включать meta родителей
export const meta: MetaFunction = ({ matches }) => {
const parentMeta = matches.flatMap(m => m.meta ?? []);
return [
...parentMeta, // включаем родительские meta
{ title: "Конкретная страница | Родительский заголовок" },
];
};
import type { LinksFunction } from "@remix-run/node";
import styles from "~/styles/page.css?url";
export const links: LinksFunction = () => {
return [
// CSS файл
{ rel: "stylesheet", href: styles },
// Preload ресурс
{ rel: "preload", href: "/fonts/Inter.woff2", as: "font", crossOrigin: "anonymous" },
// Favicon
{ rel: "icon", href: "/favicon.svg", type: "image/svg+xml" },
// Canonical URL
{ rel: "canonical", href: "https://example.com/about" },
];
};
export const links: LinksFunction = () => {
if (process.env.NODE_ENV === "development") {
return []; // Нет prefetch в dev режиме
}
return [
{ rel: "prefetch", href: "/dashboard" },
{ rel: "preconnect", href: "https://fonts.googleapis.com" },
];
};
export const meta: MetaFunction<typeof loader> = ({ data, location }) => {
const url = \`https://example.com\${location.pathname}\`;
return [
{ title: \`\${data?.post.title} | Мой блог\` },
{ name: "description", content: data?.post.excerpt?.slice(0, 160) },
// Open Graph
{ property: "og:title", content: data?.post.title },
{ property: "og:description", content: data?.post.excerpt },
{ property: "og:url", content: url },
{ property: "og:type", content: "article" },
{ property: "article:published_time", content: data?.post.createdAt },
// Twitter
{ name: "twitter:site", content: "@mysite" },
{ name: "twitter:title", content: data?.post.title },
// Robots
{ name: "robots", content: "index, follow" },
];
};