Next.js App Routerでブログを作成する
Next を使って何かしてみたい。せっかくだし話題の App Router で作りたい。
さらにさらに Cloudflare Pages も気になるなぁ
と最近思っていたことを一気に叶えるためにブログを構築しました。
理解不足で色んな躓きをしたので、自分の整理をかねて何回かにわたって構築を振り返ります。
構築の目的
今回のブログ構築はざっくり以下の目的をみたしたいと考えてスタートしました。
- Next.js(App Router)に触れられること
- SSG, SSR, ISR, CSR の差が実装でわかること
- Cloudflare Pages にデプロイすること
- Hono のセミナーで聞いてから触ってみたかった
- リポジトリ内で markdown を編集してそれをデプロイする形式であること
シンプルに何か作ってみたかったというのも大きいです。
どうしても仕事の範囲だけだと気になっているけど触ったことない技術が出てしまうので、こういう場は必要だと感じます。
計画を練る
- Vercel から出ているBlog Starter Kitを利用する
- Zenn で見つけたこちらの一連の記事を参考に構築を進める
- またまた Zenn でCloudflare Pages デプロイの事例を見つけたので参考にする
ざっくりこんな感じで事例があったのでいけそうだ!と確信。
まずは動かしてテンションを上げて行きたいので早速取り組みます。
構築
作業手順と引っかかったこと中心に記録します。
立ち上げ
プロジェクトを立ち上げましょう。
今回はyarn
の v4 系を利用する前提で進めます。
yarn create next-app --example blog-starter {project-name}
コマンドを実行したディレクトリにproject-name
フォルダが生成されます。
デフォルトで TypeScript プロジェクトになっていました。
開発サーバーを立ち上げると、ブログサイトが立ち上がります!
Blog Starter Kit の初期トップ画面
ディレクトリ構造を見てみるとトップはsrc/app/page.tsx
が表示されているようです。
詳細ページはsrc/app/posts/[slug]/page.tsx
に実装があります。
開いてみるとパスがposts/hello-world
のようになっており、[slug]
はプロジェクトルートの_posts/
下にある markdown のファイル名になっていることがわかります。
Blog Starter Kit のポスト詳細画面
app 下のディレクトリ構造がルーティングになり、その中のpage.tsx
がコンテンツになるという規約。
これが App Router か...
いきなり小問題発生
vscode で開発しているのですが、ローカルサーバーが立ち上がるものの型エラーのウニョウニョが出続ける症状が発生します。
原因は yarn の v4 系を使ったことでした。
VSCode のエディタでエラーが出ている様子
yarn の v2 以降は Plug'n'Play(pnp)と呼ばれる仕組みがデフォルトで利用されるようです。
yarn install
を実行してもnode_modules
が生成されず、.pnp.cjs
というファイルが生成されます。
vscode はデフォルトでnode_modules
を参照して型の情報があるかを判断しますが、PnP では.pnp.cjs
という単一ファイルで依存関係の解決を行うので、動くけどエディタ上はエラーになるというわけです。
yarn のチームが案内している次のコマンドを実行することで解決しました。
yarn dlx @yarnpkg/sdks vscode
この辺り完全なキャッチアップはできていませんが、以下が参考になりそうです。
markdown のスタイリング
Blog Starter Kit の初期状態は markdown を HTML 文字列にパースして表示する仕組みがすでにできています。
しかし、スタイリングは最低限のためコードを書いたり、コメントのようなことをしたりはできません。
本来ならせっせと CSS を書くところですが、ありがたいことに Zenn で利用されている markdown パーサーや CSS が公開されています。
今回はひとまずスタイリングをなんとかしたいので、次の 2 つをインストールします。
zenn-markdown-html
zenn-content-css
インストールできたらまずはパーサーを変更します。
- import { remark } from "remark";
- import html from "remark-html";
+ import m2h from "zenn-markdown-html";
export default async function markdownToHtml(markdown: string) {
- const result = await remark().use(html).process(markdown);
- return result.toString();
+ return m2h(markdown);
}
次にスタイルを当てていきます。
最初はposts/[slug]/page.tsx
の<article>
タグに当てていたのですが、タイトルや日付など markdown 本文で記載した内容以外にもスタイルが反映されて予期せぬ表示になることがありました。
パースしたコンテンツを表示するコンポーネントだけに影響するようにするのが良さそうです。
import "zenn-content-css"
type Props = {
content: string
}
export function PostBody({ content }: Props) {
return (
<div className="mx-auto mt-16 znc">
<div
dangerouslySetInnerHTML={{ __html: content }}
/>
</div>
)
}
これで以下のような記述にも対応できるようになりました!
:::message
メッセージです!
:::
まとめ
今回は Next.js の App Router で動作するブログプロジェクトを立ち上げ、Zenn と同じスタイリングをするところまでまとめました。
App Router の動作は直感的で個人的にはすぐに馴染みました。
次回はいきなりブログ本体関係ないですが気になっていた Biome の導入をまとめたいと思います。