Next.js (App Router) とTailwind CSSでマークダウンブログを作ってみた
皆さんこんにちは。Sandyマンです!
この度、私のブログ「Sandyマンのブログ」をHugoからNext.js (App Router)に移行しました🎉
今回はそのブログの実装や詳細について書いていこうと思います!
使用技術
- Next.js 13 (App Router)
- TypeScript
- Tailwind CSS
- Vercel
- Google Analytics (GA4)
だいたいこんな感じです。
Next.jsかGatsbyか
React系のフレームワークを使うのは決めていたのですが、Next.jsとGatsbyの2択でかなり迷いました。ですが結局はGatsbyの何でもかんでもプラグイン方式があまり好きじゃなかったので、Next.jsを選択しました。
デプロイ先
デプロイ先はNext.jsの開発元で相性抜群なVercelを選択しました。とても便利で助かってます。今のところ広告など収益化はしてないので、Hobbyプランで全然対応できています。
記事の管理
記事の管理は、MicroCMSやContentfulなどのヘッドレスCMSの使用も考えたのですが、Gitで管理したかったのでマークダウンファイルを読み込む感じにしてます。
ただ、ブログのソースコードと記事ファイルは分けておきたかったので、別リポジトリにしてsubmoduleで読み込むようにしています。VercelのDeploy Hooksなどを使って、記事リポジトリが更新されたら自動でビルドがかかるようにしました。
実装
実装は基本的にNext.jsの公式チュートリアルを参考にしました。Pages Routerを使ったチュートリアルですが、App Routerでもとても参考になります。
マークダウンの処理
マークダウンの処理にはunifiedを使用しています。拡張は以下のようなものを導入しました。
"@jsdevtools/rehype-toc": "^3.0.2",
"rehype-prism-plus": "^1.6.3",
"rehype-react": "^7.2.0",
"rehype-slug": "^6.0.0",
"remark-gfm": "^3.0.1",
"remark-parse": "^10.0.2",
"remark-rehype": "^10.1.0",
rehype-prism-plusでコードハイライト、rehype-reactで要素のカスタマイズ、rehype-tocとrehype-slugは目次を実装するために導入しています。
コードはこんな感じになりました。
const markdownToReact = async (markdown: string, id: string) => {
const result = (
await unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypePrism)
.use(rehypeSlug)
.use(rehypeToc, {
headings: ["h2", "h3"],
cssClasses: {
toc: "sm-toc",
link: "sm-toc-link",
listItem: "sm-toc-list-item",
list: "sm-toc-list",
},
})
.use(rehypeReact, {
createElement,
Fragment,
components: {
img: Postimg(id),
},
})
.process(markdown)
).result;
return result;
};
SSG(Static Site Generation)化する
何もしないとSSRの動的なサイトになってしまうので、SSGに対応させます。具体的には以下のようなことをしました。
- next.config.jsに
output: "export"
を追加 -
/app/posts/[slug]/page.tsx
みたいな動的ルーティングな感じのページにgenerateStaticParams
を追加(getStaticPathsみたいなやつ)
generateStaticParams
はこんな感じのやつです。
export const generateStaticParams = () => {
return allPostsData.map((post) => {
return {
slug: post.id,
};
});
};
SEO対策
一応ブログなのでSEO対策もしました。
メタデータは、各ページやlayout.tsx
でgenerateMetadata
やmetadata
を使うと設定することができます。こんな感じです。
export const metadata: Metadata = {
metadataBase: new URL("https://www.sandyman.dev"),
title: "Sandyマンのブログ",
description: "JavaScriptやLinuxなどいろいろ記事書いてます",
openGraph: {
// 省略
},
twitter: {
// 省略
}
}
generateMetadata
やmetadata
に関してはこのあたりが参考になりました。
感想
App Routerを使ってみて、今までより直感的にできる感じがしてとても良いなと思いました。SEOの設定などが簡単にできるのもとても便利ですね。ただ、しっかりServer Components
などについて理解しないと使いこなせないなと思いました。(当たり前か...)
まとめ
こんな感じでブログを作ってみました。皆さんもぜひApp Router、触ってみてください!もし記事の間違いなど訂正があれば教えてください🙏それでは!
作ったブログはこちらから↓
Discussion