next.jsでのブログの作成方法
はじめに
この記事ではこのブログについての技術的な話をします。
免責事項
この記事の内容を実行する際には自己責任でお願いします。また、あまりnextjsを理解していない人が書いているので間違っていても許してください。
環境について
この記事ではnodejsやnextjsなどの基本的な導入方法については解説しません。自分で調べてください。以下がこのブログの環境です。
(何故か埋め込みが拒否される。あと、なぜかiframeを入れるとエラーを吐く)
今回はApp Routerを採用しました。やはりAppRouterのほうがわかりやすかったです。(てかPagesRouterをほぼ触ったことがない)
ディレクトリ構成
今回はだいたいこんな感じになりました。(一部省略しています。実際のリポジトリはこちら)
1app
2├── _components
3│ ├── header.tsx , footer.tsx
4│ ├── posts.tsx
5│ ├── recentArticles.tsx
6│ └── ... その他コンポーネント
7├── posts/[title]
8│ ├── [page]
9│ │ └── page.tsx
10│ └── page.tsx
11├── layout.tsx
12├── sitemap.ts (記事の一覧のsitemap.xmlを生成するやつ)
13├── page.tsx
14├── loading.tsx
15├ @types (tsの型定義置き場)
16├── posts
17│ ├── 20230817 (この記事のやつ)
18│ │ └── 20230817.md
19│ └── ... その他記事のmdファイル
20├── public
21│ ├── sitemap.txt (homeへのリンクのみが書かれたやつ)
22│ └── ... その他画像など
23└── ... その他設定ファイルなどの山
個別ファイルの解説
app/layout.tsx
このファイルはAppRouterではホームのレイアウトを設定するために使います。今回はヘッダーとフッターを設定しました。 ヘッターとフッターはapp/_componentsから呼び出しています。(前の生コードで書いていたやつよりだいぶ楽になった) また、デザインはデジタル庁のサイトを参考にしました。
app/page.tsx
これは投稿一覧を表示するコンポーネントを呼び出すためだけのファイルです。後で記事ページにも最新の記事一覧を表示できるようにするため、分離しました。
app/[title]/page.tsx , app/[title]/[page]/page.tsx
ディレクトリに[title]が含まれているのはDynamicRoutesのためです。これを利用することで関数の引数としてparamsを受け取れます。
このファイルではレンタリング部分を完全にrender関数に切り分けています。これは複数ページ用の app/[title]/[page]/page.tsx でも全く同じように使うためです。 ここも app/_components/posts.tsx と同じようにして記事の情報と記事の内容を取得しています。
renderの返り値では次のように BlogLayout で囲っています。 app/[title]/page.tsx
BlogLayoutの最初の方の解説をします。
ほぼコメントで書いてあるとおりですが、childrenには以下のような感じで渡されます。
(例)
1<p>
2 投稿日:2023/8/17
3</p>
4<>
5 <h1 id="nextjsでのブログの作成方法">next.jsでのブログの作成方法</h1>
6 <h2 id="はじめに">はじめに</h2>
7 <p>この記事ではこのブログについての技術的な話をします。</p>
8 <!--以下省略-->
9</>
このように投稿日と本文の2つが渡されてきます。そのため、React.children.toArray(children)
でchildrenを配列に変換し、[(投稿日),(本文)]というように分割します。その後、それぞれをレンタリングします。
app/_components 内の解説
app/_components内は他のところで使い回せるようにしたコンポーネントを置いています。
posts.tsx
これは投稿記事一覧を取得するためのコンポーネントを呼び出すのと、投稿一覧というタイトルを表示します。
recentArticles.tsx
これは最新記事を指定された件数まで表示するコンポーネントです。
今回は記事を /posts上に置き、内部ディレクトリは以下のようにしました。
1posts
2├── {title} (titleはだいたい作成日)
3│ └── {title}.md
4├── {title}
5│ ├── 1.md
6│ ├── 2.md
7│ └── ... この調子で続く
このように複数ページに分割することができるようにしました(ただ、内部リンクなどの都合によってまだ使われていない)。これに伴い、記事のファイルを取得するコードがとても汚くなりました。 ↓大体のロジック
1posts内のすべてのフォルダーで
2 フォルダー内のすべてのファイルを取得
3 ファイルが1つのみだったら、pathは{folderName}で決定
4 もし、複数だったら、pathは{folderName}/1.mdで決定
5 決定したパスのファイルを取得し(ファイル取得は別の関数に切り分け済み)、その中からtitleなどの情報を取得
6 最後にPostCardコンポーネントに情報をわたし、レンタリング
このようにして記事の一覧、パス、タイトルなどの情報を取得してします。
その他のファイルの解説
sitemap.ts
これはnextjsで動的にサイトマップを生成するファイルです。これを使用することで記事を追加した際にもsitemapの変更が不要になります。
スタイルについて
今回はtailwindcssを採用しました。また、デジタル庁のデザインがきれいだったのでデジタル庁のデザインシステムを参考にさせてもらいました。これに基づくtailwind.config.jsについては別記事で書きます。
今後の課題
- コードの装飾
- githubのコードの埋め込み
- 記事ページのスタイル
おわりに
一部ゴリ押しでなんとかした面もありますが、なんとかブログが完成しました。これ以降は主にnextjsなどについて書いていこうと思っています。