8.動的ルート
変更前ソース
機能概要
ブログのようにコンテンツが動的に増えていく場合、一つ一つのコンテンツごとにページを作るのは非効率です。このように外部データの分だけページが増え、URLが増える場合、動的ルートが有効です。
機能詳細
「[id].js」のような「[」で始まり、「]」で終わるページが動的ルートになります。
実装方法
「lib/posts.js」に投稿したデータを読み込む次の関数を追加します。
// すべての投稿データのID一覧を取得する export function getAllPostIds() { const fileNames = fs.readdirSync(postsDirectory); // 次のような配列で返すことを想定 // [ // { // 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'); // gray-matter を使って、投稿したデータからメタデータを読み込む const matterResult = matter(fileContents); // 読み取ったデータとIDを繋げて返却 return { id, ...matterResult.data, }; }
「pages/posts」ディレクトリに「[id].js」ファイルを作成します。
import Layout from '../../components/layout'; import { getAllPostIds, getPostData } from '../../lib/posts'; // 投稿データのレイアウトを取得 export default function Post({ postData }) { return ( <Layout> {postData.title} <br /> {postData.id} <br /> {postData.date} </Layout> ); } // 投稿データのID一覧を取得 export async function getStaticPaths() { const paths = getAllPostIds(); return { paths, fallback: false, }; } // 投稿データを取得 export async function getStaticProps({ params }) { const postData = getPostData(params.id); return { props: { postData, }, }; }
以前作成した「first-post.js」はもう使わないので、消します。
「index.js」にリンクを付け加えます。以下コードを追加してください。
import Link from 'next/link'; // id と date と title を渡して、リンクを生成する <li className={utilStyles.listItem} key={id}> <Link href={`/posts/${id}`}> <a>{title}</a> </Link> <br /> <small className={utilStyles.lightText}> {date} </small> </li>
動作確認
http://localhost:3000、http://localhost:3000/posts/ssg-ssrとhttp://localhost:3000/posts/pre-renderingにアクセスしてそれぞれ表示されることを確認します。
さらにCSSなど組み込んで、見栄えを良くしたい場合はNext.jsのドキュメントを参考に組み込んでみてください。