pages/posts/[id].js 파일 생성
import Layout from "../../components/layout";
import { getAllPostIds } from "../../lib/posts";
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
}
export default function Post() {
return <Layout>...</Layout>;
}
lib/posts.js
export function getAllPostIds() {
const fileNames = fs.readdirSync(postsDirectory);
// Returns an array that looks like this:
// [
// {
// params: {
// id: 'ssg-ssr'
// }
// },
// {
// params: {
// id: 'pre-rendering'
// }
// }
// ]
return fileNames.map((fileName) => {
return {
params: {
id: fileName.replace(/\.md$/, ""),
},
};
});
}
export function getPostData(id) {
const fullPath = path.join(postsDirectory, `${id}.md`);
const fileContents = fs.readFileSync(fullPath, 'utf8');
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents);
// Combine the data with the id
return {
id,
...matterResult.data,
};
}
pages/posts/[id].js
import Layout from "../../components/layout";
import { getAllPostIds, getPostData } from "../../lib/posts";
export async function getStaticProps({ params }) {
const postData = getPostData(params.id);
return {
props: {
postData,
},
};
}
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
}
export default function Post({ postData }) {
return (
<Layout>
{postData.title}
<br />
{postData.id}
<br />
{postData.date}
</Layout>
);
}
localhost:3000/posts/ssg-ssr의 url로 가보면 페이지가 뜨는 것을 확인할 수 있음
여기서 신기한 것은 ssg-ssr이나 pre-rendering 페이지를 만들지 않았지만 페이지가 뜨는 것을 알 수 있다.
Fallback
Fallback: false
를 통해 getStaticpaths
에서 우리가 주지 않은 id 값에 대한 페이지를 처리 함
npm install remark remark-html
lib/posts.js
import { remark } from 'remark';
import html from 'remark-html';
export async function getPostData(id) {
const fullPath = path.join(postsDirectory, `${id}.md`);
const fileContents = fs.readFileSync(fullPath, 'utf8');
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents);
// Use remark to convert markdown into HTML string
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
export async function getStaticProps({ params }) {
const postData = await getPostData(params.id);
return {
props: {
postData,
},
};
}
export default function Post({ postData }) {
return (
<Layout>
{postData.title}
<br />
{postData.id}
<br />
{postData.date}
<br />
<div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
</Layout>
);
}
markdown을 html 형식으로 바꿔주는 것이 remark의 역할이다.
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: true,
};
}
import { useRouter } from "next/router";
export default function Post({ postData }) {
const router = useRouter();
if (router.isFallback) {
return <div>Loading..</div>;
}
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>
);
}
fallback true
시
useRouter를 통해 router.isFallback에서 Loading이 뜬다.
이미 제네레이션 되어 있다면 loading 문구가 뜨지 않는다.
// pages/404.js
export default function Custom404() {
return <h1>404 - Page Not Found!!!!!!</h1>;
}
api/hello.js
export default function handler(req, res) {
res.status(200).json({ text: "Hello" });
}
import Layout from "../../compoenents/layout";
import { getAllPostIds, getPostData } from "../../lib/posts";
import Head from "next/head";
import utilStyles from "../../styles/utils.module.css";
import { useRouter } from "next/router";
import { useEffect } from "react";
export async function getStaticProps({ params }) {
const postData = await getPostData(params.id);
return {
props: {
postData,
},
};
}
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
}
export default function Post({ postData }) {
const router = useRouter();
useEffect(() => {
const getText = async () => {
const res = await fetch("/api/hello");
const data = await res.json();
alert(data.text);
};
getText();
}, []);
if (router.isFallback) {
return <div>Loading..</div>;
}
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>
);
}