NextJSのチュートリアルをやってみる

目次
まずはチュートリアルをやってみる
チュートリアルは npx だったけど、yarn を使ってやってみる
yarn create next-app nextjs-blog
cd nextjs-blog
yarn dev
Link
GatsbyJS の時は、URL の指定は to="/posts/1"とかだったけど、NextJS は href="/posts/1"になる。
import Link from "next/link";
export default function Home() {
return (
<Layout>
<section>
(略)
<Link href={`/posts/${id}`}>
<a>{title}</a>
</Link>
(略)
</section>
</Layout>
);
}
Image
public フォルダ内に images フォルダを作り、そこに画像を入れておく。
import Image from "next/image";
const Hoge = () => (
<Image src="/images/hoge.png" height={144} width={144} alt="XXXXXXXX" />
);
Metadata
Layout.js ファイル内に Head コンポーネントを配置し、meta データの設定を行う。
import Head from "next/head";
export default function Layout({ children }) {
return (
<Head>
<title>タイトル</title>
<link rel="icon" href="/favicon.ico" />
<meta name="description" content="説明文" />
</Head>
);
}
CSS(Global Style)の設定
CSS の Global Style を設定したい場合は、pages 以下に_app.js ファイルを作成する。
styles フォルダを(プロジェクトの)トップレベルに作成し、そのフォルダ内に global.css を作成し、_app.js 内で読み込む。
import "../styles/global.css";
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}
固定ページの作成
固定ページ(About、404 など)を作成する時は、pages フォルダ内に配置する。
// pages/404.js
export default function Custom404() {
return <h1>404 - Page Not Found</h1>;
}
md ファイルの作成
posts フォルダを(プロジェクトの)トップレベルに作成し、そのフォルダ内に md ファイルを作成する。
---
title: "NextJSのチュートリアルをやってみる"
date: "2022-06-21"
---
Markdown ファイルから meta 情報をパースするために、gray-matter ライブラリ をインストールする。
yarn add gray-matter
lib フォルダを(プロジェクトの)トップレベルに作成し、そのフォルダ内に posts.js ファイルを作成する。
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
const postsDirectory = path.join(process.cwd(), 'posts');
export function getSortedPostsData() {
// Get file names under /posts
const fileNames = fs.readdirSync(postsDirectory);
const allPostsData = fileNames.map((fileName) => {
// Remove ".md" from file name to get id
const id = fileName.replace(/\.md$/, '');
(略)
index.js ファイルに、以下を追記する。
import { getSortedPostsData } from "../lib/posts";
export async function getStaticProps() {
const allPostsData = getSortedPostsData();
return {
props: {
allPostsData,
},
};
}
allPostsData を受け取って、map で展開する。
export default function Home({ allPostsData }) {
return (
<Layout>
<section>
<h2>Blog</h2>
<ul>
{allPostsData.map(({ id, date, title }) => (
<li key={id}>
{title}
<br />
{id}
<br />
{date}
</li>
))}
</ul>
</section>
</Layout>
);
}
動的ファイルの作成
動的にページを作成する時は、pages ディレクトリ内に posts フォルダを作成し、そこに[id].js ファイルを配置する。
Markdown に書かれた内容を読み込む為に、remark ライブラリをインストールする。
yarn add remark remark-html
lib/posts.js ファイルに以下を追記する。
import { remark } from "remark";
import html from "remark-html";
export function getAllPostIds() {
const fileNames = fs.readdirSync(postsDirectory);
return fileNames.map((fileName) => {
return {
params: {
id: fileName.replace(/\.md$/, ""),
},
};
});
}
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,
};
}
pages/posts/[id].js ファイルに、以下を追記。
import { getAllPostIds, getPostData } from "../../lib/posts";
export default function Post({ postData }) {
return (
<Layout>
{postData.title}
<br />
{postData.id}
<br />
{postData.date}
<br />
<div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
</Layout>
);
}
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
}
export async function getStaticProps({ params }) {
const postData = await getPostData(params.id);
return {
props: {
postData,
},
};
}
markdown ファイルのファイル名から.md の拡張子を削除したものを URL のパス名として取り出し、それを使って個別記事にアクセス可能にしている。
getStaticPaths と getStaticProps については、以下に詳しく書かれています。
Date Format
日付のフォーマットを行うので、date-fns ライブラリをインストールする。
yarn add date-fns
components フォルダ内に、date.js ファイルを作成し、以下を記述する。
import { parseISO, format } from "date-fns";
export default function Date({ dateString }) {
const date = parseISO(dateString);
return <time dateTime={dateString}>{format(date, "LLLL d, yyyy")}</time>;
}
pages/posts/[id].js ファイルの記述を変更する。
import Date from "../../components/date";
export default function Post({ postData }) {
return (
<Layout>
{/* Replace {postData.date} with this */}
<Date dateString={postData.date} />
</Layout>
);
}
日付のフォーマットを変更したい場合は、以下を参考にする。