변수가 있는 정적 페이지의 경로를 만들 때 사용한다.
이전 글 - getStaticProps에 이어서 작성함.
blog
컴포넌트를 인덱스로 하는 폴더를 생성한 후, [id].jsx
같은 Pages를 생성한다.
# directory tree
└ pages
└ blog
└ index.jsx
└ [path].jsx
└ blog
└ 01-first-file.md
└ 02-second-file.md
└ 03-third-file.md
index.jsx
의 getStaticProps
에 path
를 추가한다.
import { readdirSync, readFileSync } from "fs";
import matter from "gray-matter";
const Blog = ({ posts }) => {
return (
<div>
<h1>
Latest Posts:
</h1>
{posts?.map((item, idx) => (
<div key={idx}>
<span>{item.title}</span>
<div>
<Link href={`/blog/${item.path}`}>
<a>
<span>
{item.date} / {item.category}
</span>
</a>
</Link>
</div>
</div>
))}
</div>
);
};
export default Blog;
export async function getStaticProps() {
const posts = readdirSync("./blog").map((file) => {
const content = readFileSync(`./blog/${file}`, "utf-8");
const [path, _] = file.split(".");
return { ...matter(content).data, path };
});
return {
props: { posts },
};
}
파일명이 01-first-file.md
라면 경로는 http://localhost:3000/blog/01-first-file
이 된다. 이 경로를 [path].jsx
에게 알려주기 위해 getStaticPaths()
함수를 사용한다.
getStaticPaths()
페이지가 동적 경로를 가지고 있거나
getStaticProps
를 사용한다면, 정적으로 생성하기 위해 경로 목록을 정의할 필요가 있다.동적 경로를 사용하는 페이지에서
getStaticPaths
함수를 export할 때,Next.js
는getStaticPaths
로부터 구체화된 모든 경로를 정적으로 pre-render할 것이다.
getStaticPaths
는 반드시getStaticProps
와 함께 사용해야만 하며,getServerSideProps
와는 함께 사용할 수 없다.
Next.js
Docs - getStaticPaths
import { readdirSync } from "fs";
const Post = () => {
return <h1>post</h1>;
};
export function getStaticPaths() {
const files = readdirSync("./blog").map((file) => {
const [name, extension] = file.split(".");
return { params: { path: name } };
});
return {
paths: files,
fallback: false,
};
}
export function getStaticProps() {
return { props: {} };
}
export default Post;
getStaticPaths()
에는 paths
와 fallback
두 가지 인자가 필요하다. 전자는 배열이고, 후자는 boolean과 blocking
을 가진다. 백그라운드에서 실행할 때는 fallback: true
를, 최초 렌더링 전에 호출할 때는 fallback: blocking
을 사용한다. 그 외는 fallback: false
를 사용한다.
경로가 생성되었으니 이제 문서 내용을 가져올 수 있다. getStaticProps
에서 문서를 가져온다. Node.js
가 아닌 다른 라이브러리로 front matter
를 읽어올 수 있다. gray-matter
의 matter()
와 remark-html
을 사용한다.
# remark-html 설치
npm i remark-html remark-parse unified
import matter from "gray-matter";
import remarkHtml from "remark-html";
import remarkParse from "remark-parse/lib";
import { unified } from "unified";
export const getStaticProps = async (ctx) => {
const { content } = matter.read(`./posts/${ctx.params?.name}.md`);
const { value } = await unified()
.use(remarkParse)
.use(remarkHtml)
.process(content);
return { props: { post: value } };
};
가져온 props를 컴포넌트에 넘겨준다.
const Post = ({post}) => {
return <h1>{post}</h1>;
};
클라이언트 페이지에는 마크다운 문법으로 쓴 내용이 <h1>my third file</h1> <p>congratulations!</p>
로 파싱되어 나온다.
참고
노마드 코더 - 캐럿마켓 클론코딩
Next.js Docs - getStaticPaths
npmjs package - remark-html