Dynamic Routes
기본개념
사용 라이브러리
Render Markdown
npm install remark remark-html
Formatting the Date
import { parseISO, format } from "date-fns";
export default function Date({ dateString }) {
const date = parseISO(dateString);
★ format은 변경 가능
return <time dateTime={dateString}>{format(date, "LLLL d, yyyy")}</time>;
}
코드 설명
posts.js
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import remark from 'remark'
import html from 'remark-html'
★ 각 파일의 이름만 id값으로 뽑아 배열로 반환
export function getAllPostIds() {
const fileNames = fs.readdirSync(postsDirectory)
★ map()함수: 배열의 특정 값만 뽑아서 리스트로 반환
return fileNames.map(fileName => {
return {
params: {
id: fileName.replace(/\.md$/, '')
}
}
})
}
★ id, html로 변환된 마크다운, matterResult.data(title, date 포함) 리턴
export async function getPostData(id) {
const fullPath = path.join(postsDirectory, `${id}.md`)
const fileContents = fs.readFileSync(fullPath, 'utf8')
★ gray-matter를 사용해서 metadata section 부분을 파싱
const matterResult = matter(fileContents)
★ remark를 사용해서 마크다운 언어의 콘텐트를 html로 변환
const processedContent = await remark()
.use(html)
.process(matterResult.content)
const contentHtml = processedContent.toString()
// Combine the data with the id and contentHtml
return {
id,
contentHtml,
...matterResult.data
}
}
[id].js
- Next.js에서 dynamic routes를 사용하기 위해 파일명을 []로 감싼다.
- 각 파일(여기서는 md파일)을 render하는 페이지
import Layout from '../../components/layout'
import { getAllPostIds, getPostData } from '../../lib/posts'
import Head from 'next/head'
import Date from '../../components/date'
import utilStyles from '../../styles/utils.module.css'
export default function Post({ postData }) {
return (
<Layout>
<Head>
<title>{postData.title}</title>
</Head>
<article>
<h1 className={utilStyles.headingXl}>{postData.title}</h1>
<div className={utilStyles.lightText}>
<Date dateString={postData.date} />
</div>
<div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
</article>
</Layout>
);
}
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
}
}
★ build time시 가장 먼저 실행됨
export async function getStaticProps({ params }) {
★ import한 posts.js의 getPostData()를 호출
★ id, html로 변환된 마크다운, matterResult.data(title, date 포함)를 받음
const postData = await getPostData(params.id);
return {
props: {
postData,
},
};
}
index.js
<section className={`${utilStyles.headingMd} ${utilStyles.padding1px}`}>
<h2 className={utilStyles.headingLg}>Blog</h2>
<ul className={utilStyles.list}>
{allPostsData.map(({ id, date, title }) => (
<li className={utilStyles.listItem} key={id}>
★ posts/[id].js를 호출
★ 파일명이 id 값이 되며 dynamic routes가 생성되어 있어 해당 파일의 페이지가 호출되는 방식
<Link href={`/posts/${id}`}>
{title}
</Link>
<br />
<small className={utilStyles.lightText}>
<Date dateString={date} />
</small>
</li>
))}
</ul>
</section>