[Next.js] - v13.2 Feature: Metadata

NoowaH·2023년 3월 12일
12
  • v13.2 에 추가된 빌트인 기능
  • head.js 파일 대체 (🔴 deprecated)

기본 사용 방법

import { Metadata } from 'next'

export const metadata: Metadata = {
	title: 'NoowaH Blog',
	description: 'Generated by create next app',
}

const page = () => {
	return <div>NoowaH Blog</div>
}

export default page

Options

more on : beta.nextjs.org | Metadata


Basics

export const metadata = {
  generator: 'Next.js',
  applicationName: 'Next.js',
  referrer: 'origin-when-cross-origin',
  keywords: ['Next.js', 'React', 'JavaScript'],
  authors: [{ name: 'Seb' }, { name: 'Josh', url: 'https://nextjs.org' }],
  colorScheme: 'dark',
  creator: 'Jiachi Liu',
  publisher: 'Sebastian Markbåge',
  alternates: {},
  formatDetection: {
    email: false,
    address: false,
    telephone: false,
  },
};
<meta name="application-name" content="Next.js">
<meta name="author" content="Seb"/>
<link rel="author" href="https://nextjs.org"/>
<meta name="author" content="Josh"/>
<meta name="generator" content="Next.js">
<meta name="keywords" content="Next.js,React,JavaScript">
<meta name="referrer" content="origin-when-cross-origin">
<meta name="color-scheme" content="dark">
<meta name="creator" content="Jiachi Liu">
<meta name="publisher" content="Sebastian Markbåge">
<meta name="format-detection" content="telephone=no, address=no, email=no">

OpenGraph

export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'The React Framework for the Web',
    url: 'https://nextjs.org',
    siteName: 'Next.js',
    images: [
      {
        url: 'https://nextjs.org/og.png',
        width: 800,
        height: 600,
      },
      {
        url: 'https://nextjs.org/og-alt.png',
        width: 1800,
        height: 1600,
        alt: 'My custom alt',
      },
    ],
    locale: 'en-US',
    type: 'website',
  },
};
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:url" content="https://nextjs.org/" />
<meta property="og:site_name" content="Next.js" />
<meta property="og:locale" content="en-US" />
<meta property="og:image:url" content="https://nextjs.org/og.png" />
<meta property="og:image:width" content="800" />
<meta property="og:image:height" content="600" />
<meta property="og:image:url" content="https://nextjs.org/og-alt.png" />
<meta property="og:image:width" content="1800" />
<meta property="og:image:height" content="1600" />
<meta property="og:image:alt" content="My custom alt" />
<meta property="og:type" content="website" />

Dynamic Routes Metadata

  • generateMetadata 라는 예약된 이름의 비동기 함수 사용
  • return type : Promise<Metadata>
export const generateMetadata = async ({ params }: any): Promise<Metadata> => {
	return {
		title: 'test',
		description: params.slug,
	}
}

const Page = ({ params }: any) => {
	return <div>{params.slug}</div>
}

export default Page

Create metadata using async data

fetch

  • fetch API를 사용하게 될 경우 페이지 컴포넌트에서 비동기 함수를 요청하는 방식과 동일하게 호출
  • 기본 fetch API를 사용하게 될 경우, 호출된 비동기 함수가 동일한 함수라면 내부적으로 알아서 캐싱을 하여 중복 요청을 막음
export const getData = async(id: string) => {
	const res = await fetch(`endpoint/${string}`)
	return res.json()
}

export const generateMetadata = async ({ params }: any): Promise<Metadata> => 
{
	const data = await getData(params.id)
	return {
		title: data.title,
		description: params.slug,
	}
}

const Page = async ({ params }: any) => {
	const data = await getData(params.id)
	return <div>{params.id}</div>
}

export default Page

custom API

  • fetch를 사용하지 않는 경우 getData()cache()로 감싸주면 해결
  • 🌟 cache로 감싸진 함수는 export하여
    - cache: React 18의 빌트인 서스펜스 캐시
    - 함수를 export하여 다른 컴포넌트에서도 사용이 가능하며 동일한 요청이 필요한 컴포넌트에서의 중복 요청을 막을 수 있다
const getData = cache(async (slug: string) => {
	// custom api without fetch
})

export const generateMetadata = async ({ params }: any): Promise<Metadata> => {
	const post = await getData(params.slug)
	return {
		title: post?.title,
	}
}

const PostDetailPage = async ({ params }: any) => {
	const post = await getData(params.slug)
	return (
	return post ? (
		<div>{post.title}</div>
	) : null
}

Title Template

  • 🌟 다이나믹 페이지의 상위 경로 (주로 리스트를 뿌려주는 페이지) 기준의 layouts.tsx 파일에서 하위 경로 페이지들이 동일하게 사용할 template 설정 가능

/app/posts/layouts.tsx

import { Metadata } from 'next'

export const metadata: Metadata = {
	title: {
		default: 'Posts', // <title>Posts</title>
		template: 'Posts | %s',
	}
}

interface Params {
	children: ReactNode
}

const layouts = ({ children }: Params) => {
	return (
		<div>{children}</div>
	)
}

export default layouts

/app/posts/[slug]/page.tsx

import { Metadata } from 'next'
  
export const generateMetadata = async ({ params }: any): Promise<Metadata> => {
	return {
		title: params.slug, // <title>Posts | {slug}</title>
	}
}

const page = ({ params }: any) => {
	return <div>{params.slug}</div>
}

export default page
profile
조하운

0개의 댓글