目指すは簡単にカスタマイズできるブログのスケルトンを作ること。それではレイアウトの構想から。
レイアウト
app/
-
posts/[slug]/page.tsx
- * ブログの記事ページ
- * 動的ルーティング[1-1]を使うことでMDファイルでURLを指定できる
- * resume(CV)やprojects, aboutページなどの追加にも対応できる
- * 今このページも同じ構成になっている
components/
contents/
-
posts/
- * ブログのコンテンツになるMDファイルを格納するディレクトリ
- * 開発が終わってからは、このディレクトリだけ行き来すれば良い
lib/
- * ユーティリティやカスタムフックなどを集めるディレクトリ
- * dateやMDファイルの読み込みなどの処理をここに集める
public/
- * 同じくNext.jsのコンセプトにより、assetsは
public/
に置かないといけないお約束
- * MDファイルで使われる画像などが入る
- ↪︎ ex)
public/ポスト別/MDに入るイメージ.png
ディレクトリを一個一個掘るのも大変なので一気に作る。
- * 緑色の部分が追加された部分(diff)
- * 補足が必要だと思われる部分はコードの下に記載
app/layout.tsx
app/globals.css
- * L13: スクロールバーの有無でレイアウトの崩れ(ガタツキ)がないように
scrollbar-gutter
を常に設定する
components/constants.ts
components/header.tsx
- * L1: ヘッダーはinteractive要素が多いため
"use client"
を追加
- * SSGでビルドをするため
"use client"
を追加しなくても、"next/link"
は使える
- * L21, L24:
Home
とAbout
はダミー
components/footer.tsx
実装追加: Markdown ポスティング[commit]
まずはパッケージをインストール。
app/page.tsx
app/posts/[slug]/page.tsx
- * L11: リンターの働きで行替えになっているが、
params: { slug }
がこのファイルの[slug]
[1-2]に対応している(取ってきている)
- * L13: TypeScriptの型定義で
slug
がstring
であることを示している
- * L20-26:
remark
とrehype
を使ってMarkdown
をHTML
に変換
- * L22:
remark-parse
: MDをAST(Abstract Syntax Tree)に変換
- * L23:
remark-rehype
: ASTをHTML ASTに変換
- * L24:
rehype-stringify
: HTML ASTをHTMLに直列化(シリアライズ, serialization)
- *
allowDangerousHtml
はMDファイルにHTMLタグを埋め込むことを可能にする
- ↪︎ MDファイルが掲示板の投稿、リモートアクセスなどの信頼できないソースから取得される場合、
XSS(Cross-Site Scripting)
脆弱性のリスクがあるため、デフォルトではfalse
になっているが、今回は自分で作成したローカルのMDファイルでビルドするため使用
- ↪︎ MDファイルの中のHTMLタグを読み込むために、
rehype-raw
を使うこともできるが、rehype-stringify
のオプションで十分なので余分なパッケージは入れたくなかった
- * L26:
unified()
はVFileオブジェクト
返すので、toString()
でHTML文字列に変換
- * L35: 上で処理したHTMLをJSX(TSX)に変換せずにそのままレンダリング
- L42-48:
generateStaticParams()
: SSGビルド時、動的ルーティングをスタティックに生成するための関数
- * L45: 仕様上、
slug
がない場合は、return [];
を返すよう公式に書いてあるが、そうするとビルドができない問題があり、臨時的にこのような書き方を取っている
- ↪︎
not-found
ページは存在しない
- ↪︎ あくまでも
slug
がない時だけの話で、slug(MDファイル)
がある場合は関係ない
contents/posts/.gitkeep
- * このファイルは
空ファイル
で、内容は意味を持たない。空のcontents/posts/
ディレクトリをGitに追跡させるために追加してある[2]
- ↪︎ Gitは空のディレクトリを追跡しないためPushできないが、この仕様によって
lib/posts.ts
のgetPostSlugs()
がディレクトリを探せず、ビルドが失敗する
- ↪︎ この件も、
return [{ slug: "not-found" }];
と似た話で、slug(MDファイル)
がある場合は関係ない(消しても良い)
contents/posts/lipsum.md
- * L1-5: このブロックがMDファイルのメタデータ(Front Matter)になる
- * L7: MDファイルの中でHTMLタグを使っている
- ↪︎ 続くTailwindCSSの設定で、MDファイルの中でもTailwindCSSのクラスを使えるようにする
- ↪︎ JSX(TSX)ファイルの中でTailwindCSSを使う時との違いは、
className
ではなく、class
にすること
lib/date.ts
lib/posts.ts
tailwind.config.ts
- * L8: MDファイルの中でもTailwindCSSのクラスを使えるようにする
終わりに
これでスケルトンが完成した。
ついでに、TailwindCSS本家のtailwindcss-typographyを使うことで、簡単にブログのスタイルをプロのように整えることができるのでシンプルな導入方法も残しておく[commit]。
カスタマイズはできるが、このプラグインのデフォルトのmax-widthやフォントの色、大きさなどが個人的に合わず、逆に修正箇所が多くなり追えなくなったので、私は使っていない。
機会があれば、このブログで使っているTailwindCSSの設定やダークモードに関しても書いていきたい。
その時にはまたblog-exampleリポジトリを更新していくので、blog-exampleリポジトリ
を<user>.github.io
のリポジトリ名にしてフォークしてもらったら、最新の情報を取得できるようになる。
1: SSG環境でももちろん動的ルーティング(Dynamic Routes)を使える。[括弧の中]
が必ずslug
である必要はなく、別に[banana]
でも良いが命名は慎重にしていきたい。return 1-1↩ | return 1-2↩
2: .gitkeep
はde facto standardのようなもので、今回は無理やりディレクトリをPushしたかったので入れてあるがMDファイルを追加したら削除しても良い(残しておいても良い)。[stack overflow記事] return↩