こんにちは!4月から事業部が変わり、ビジネスアクセラレーション事業部の大瀧優杏です!🎀
今回はNext.js の学習を通じて、Markdown ファイルをデータソースにしたエンジニアブログアプリをローカルで作成しました 👏🏻
この記事では、学んだことをまとめましたので、ぜひ最後までご覧ください!
技術スタック
| 項目 | 内容 |
|---|---|
| フレームワーク | Next.js(Pages Router) |
| 言語 | JavaScript / JSX |
| スタイリング | CSS Modules |
| Markdown パーサー | gray-matter / remark / remark-html |
| Node.js バージョン | v22.22.3(推奨) |
ディレクトリ構成
nextjs-microblog/
├── components/
│ ├── Layout.js # 共通レイアウト(ヘッダー含む)
│ └── layout.module.css
├── lib/
│ └── posts.js # Markdownデータ取得ロジック
├── pages/
│ ├── _app.js
│ ├── _document.js
│ ├── index.js # トップページ(記事一覧)
│ └── posts/
│ └── [id].js # 記事詳細(動的ルート)
├── posts/ # Markdownブログ記事
│ ├── ssg-ssr.md
│ ├── pre-rendering.md
│ ├── prerendering-about.md
│ └── react-next.md
├── public/
│ └── images/ # サムネイル画像
└── styles/
├── globals.css
├── Home.module.css
└── utils.module.css
Next.js ってなに?
React のフレームワークで、プリレンダリングに対応しているのが大きな特徴です。
プリレンダリングって?
通常の React(Create React App など)は、ブラウザがページを開いたときに JavaScript をダウンロード → 実行 → HTML を組み立てる という流れで画面を表示します。
つまり JavaScript の処理が終わるまで、ユーザーには真っ白な画面が表示され続けます。
Next.js のプリレンダリングは、
あらかじめサーバー側で HTML を生成しておいて、ブラウザにはその完成済みの HTML を渡すという流れになります。
【通常の React】
ブラウザ → JS をダウンロード → JS を実行して HTML を組み立て → 画面表示
【Next.js(プリレンダリング)】
ブラウザ → 完成済みの HTML を受け取る → 画面表示
↑ 最初からコンテンツが見える!
ユーザーが画面を開いた瞬間にコンテンツが表示されるので、体感の速さが全然違います。
SEO 的にも、クローラーが HTML をそのまま読めるのでインデックスされやすいというメリットもあります!
レンダリング方式:SSG と SSR
Next.js には 2 つのレンダリング方式があって、ページごとに使い分けできます。
SSG(Static Site Generation)― 静的生成
ビルド時に 1 度だけ HTML を生成する方式。リクエストにすぐ返却できます。
公式でも推奨されていて、このブログもSSGで作りました。
適したページ:ブログ、ドキュメント、商品ページなど更新頻度が低いコンテンツ
SSR(Server-Side Rendering)― サーバーサイドレンダリング
ブラウザからリクエストごとに、サーバーが HTML を生成する方式。
常に最新データを返せますが、SSG よりはやや遅いです。
適したページ:SNS のユーザープロフィールなど更新が発生するコンテンツ
ルーティング
pages/ 配下のディレクトリ名・ファイル名が、そのまま URL になります。直感的でわかりやすいですね👏🏻
pages/
├── index.js → /
└── posts/
└── first-post.js → /posts/first-post
SSG でのデータ取得
ここがちょっと難しかったです。💦SSG で外部データ(Markdown など)を取得するには、専用の関数を使う必要があります。
getStaticProps
ビルド時に外部データを取得して、コンポーネントに props として渡す関数です。
SSG でしか使えないので注意!
export async function getStaticProps({ params }) {
const postData = await getPostData(params.id);
return {
props: {
postData,
},
};
}
getStaticPaths
動的ルート([id].js など)で SSG を使うときに必要になる関数です。
「どのパスに対してページを生成するか」を事前に設定します。
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
}
動的ルートでは getStaticPaths と getStaticProps を必ずセットで書く必要があります。片方だけだとエラーになります。🚨
// pages/posts/[id].js
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,
},
};
}
export default function Post({ postData }) {
return (
<div>
<h1>{postData.title}</h1>
</div>
);
}
fallback オプションについて
fallback の値によって、paths に含まれていないURLにアクセスしたときの挙動が変わります。
| 値 | 動作 |
|---|---|
false |
paths 外のURLは 404 ページを返す |
true |
paths 外のURLでも、サーバーサイドが動的にページを生成してくれる |
今回は false にしたので、存在しない記事のURLにアクセスすると 404 になります。

Markdown → HTML 変換
gray-matter で frontmatter(タイトル・日付・サムネイル)を、remark + remark-html で本文を HTML に変換します。
// lib/posts.js const matterResult = matter(filecontents); const blogContent = await remark().use(remarkHtml).process(matterResult.content);
起動方法
bash # 依存パッケージのインストール npm install # 開発サーバー起動 npm run dev # → http://localhost:3000 でアクセス可能
完成したアプリケーション
トップページ(記事一覧)

記事詳細ページ

動作確認済み環境
- OS: macOS
- Node.js: v22.22.3
- ブラウザ: Chrome / Safari
最後に
今回初めてNext.jsを扱いましたが、Reactベースのフレームワークということもあり、とっつきやすく感じました!
ローカル環境のみで完結してしまったのが少し心残りですが、時間ができればビルド&デプロイにも挑戦していきたいと思います!
記事の内容は以上になります!
最後までお読みいただきありがとうございました🙇🏻♀️