当ブログの作り方
公開: 2023-10-16 改訂: 2023-10-16
何についてまとめた記事か?
当個人ブログをどう作ったかについて簡単にまとめてみようと思います。
わりと簡単でかつ『いかにも』感がありますがモダンな技術スタックで実装したので、楽しく勉強しながら真似することもできるような気がしています。
↓なお、ソースコードはこちらになります。
https://github.com/RikiyaOta/blog
そんなに凝ったこともしていないので、Qiita でも zenn でもなく、ここにしました。
なぜ個人ブログを自前で用意したのか?
まずここから一応残しておきます。
正直はてなブログや、Qiita/zenn、あるいは Mathlog で十分だろうとは思いました。
しかし、そんなに積極的に人にアピールしたいわけでもない備忘録やポエムも含めて日々考えた・学んだことを『気軽に』(←ここ大事)書き残せる場所が欲しいなぁと感じていました。
また、今回実装したような「シークレット記事」機能(後述)など、自分で実装しているからこそ柔軟にブログをコントロールできるところも魅力だと感じ、勉強も兼ねてやってみようと思い作ってみました。今後も少しずつ改善をしていきたいと考えています。
構築にかかった費用
ドメインの登録料・更新料だけです。他は全て無料で作ることにだけこだわってみました。インフラの詳細などは後述したいと思います。
貧乏根性が出てしまったなぁ、とは思いますが、『気楽に書くこと』が達成したい目標の1つだったので、変に運用費用がかかると執筆活動に余計なストレスがかかってしまうと考えたので、ここは譲れないと思いました。
余談: kyoto ドメインはなかなか料金が高いですね。ただ、大好きな京都のドメインを取得することができて大変満足しております😁
技術スタック
README にも簡単に書いたのですが、基本的には Astro で SSG したコンテンツを Cloudflare Pages で配信するという構成を取っています。
ざっと使用技術をまとめてみます。それぞれの簡単な補足や導入意図は後述します。
Astro
まず、自分でフロントエンドを実装するということで、経験のある React (JSX) を使いたいと考えました。あくまで気軽な趣味なので、あまり学習コストはかけたくないと思いました。
なので、最初は Next.js を使うことを考えていました。やはり有名なフレームワークなので一度は触っておきたいかなと思ったのと、利用しているエンジニアの方も多いので情報収集しやすいだろう考えたことが大きな理由です。また、ブログサイトということであまり動的な機能は入れないだろうと考えていましたので、SSG できることも採用するには十分だろうと思っていました。
Next.js で簡単に実装を進めていたそんなときに、たまたま以下の記事を見かけ、Astro の存在を知りました。(もっと調査を先にしておくべきでしたね、反省反省🙏)
https://www.publickey1.jp/blog/23/astro_30javascriptspa.html
ビルド後のコンテンツに javascript を全く含めないような形でwebサイトを生成できるというのが、僕の目にはとても新鮮に写りました。
静的コンテンツが主になるブログという要件に対して、シンプルかつハイパフォーマンスなサイトを構築できる Astro を知り、「絶対これやん。」と思ってすぐ導入しました。
実際に開発する際には、.astro
というちょっと特殊なファイルをベースに開発をしますが、基本的なコーディングは素の HTML/CSS/Javascript を触る感覚に近いです。
そこに加えて Typescript を使えたり、JSX と同じようなシンタックスが用意されていたりで、既にフロントエンド開発の経験が少しでもある人にはかなり馴染みやすい開発体験になっているのではないかと感じました。
また、Astro は基本的に SSG をするのですが、もちろん SSR にすることもできたり、Astro Islands といった仕組みによるより柔軟なレンダリングの戦略をとることができることもできます。このように機能も豊富なことから、ブログ実装の要件が増えてしまったとしても十分に対応できるだろうと考えたことも大きかったです。
Cloudflare Pages
元々 Cloudflare Workers や Hono きっかけで Cloudflare のサービスに興味を持っていたので、存在自体は知っていました。
今回のブログ構築のインフラを検討しようとしたときに、真っ先に候補に上がりました。無料でも十分にスケールするようなWebサイトを公開できますし、GitHub との連携もバッチリです。また、Cloudflare Pages Functions という機能もあり、サーバーサイド(というか Edge)上でコードを実行することも柔軟に行うことができます。
Cloudflare のサービスをもっと知りたいなと考えていたこともあったので、ぜひ使ってみたいと思い、インフラには Cloudflare Pages を使うことにしました。
あ、実は前に個人ブログを少し運営していたときは Vercel を使っていましたが、無料プランでは商用利用の制限がめっちゃ厳しいことを知って辞めました。実際にやるかはわかりませんが、広告貼ったりする選択肢も残しておきたいと思いました。
microCMS
最初はコンテンツを直接 Markdown で書いて GitHub にコミットしておこうかなと考えていました。
しかしこの運用は簡単そうに見えていくつか問題があるなと感じていました:
- ブログ記事が GitHub 経由で公開されてしまう(※ ソースコードは公開する前提)
- スマホで書きにくい
- 記事の公開の作業で Git の操作が必要になってしまう
特に2点目3点目の問題が大きいなと感じました。
ふと思いついたことを文字に起こす作業はスマホでも気軽に実施したです。しかし、PCでコーディングするような形でしか記事を書くことができない形だと、この気軽さが実現できないと思いました。また、記事の執筆をしたいだけなのにわざわざブランチを作ったりマージしたりといった煩雑な作業もしたくありません。
なので、コンテンツ自体は GitHub から切り離してしまった方が色々とやりやすいと考え、Headless CMS の導入を検討しました。
いくつか調べてみましたが、日本製の microCMS を選んでみました。日本製ということで情報も集めやすいだろうと思ったのと、無料プランでも十分使えるだろうと考えたことが理由です。特に、スマホからでもリッチテキストエディタを使うことができたり、webhook の機能があることも魅力でした。また、Astro や Cloudflare Pages との連携を紹介した記事がいくつか公開されていたことも、導入しやすいと感じた点です。
https://blog.microcms.io/astro-microcms-introduction/
https://blog.microcms.io/webhook-cloudflare-vercel/
TailwindCSS
まあこれは、色々スタイル(CSS)を試行錯誤しながら書くのも勉強になるとは思うのですが、それよりはいろんな実装例を参考にしたりコピペしたりして手軽に実装したいと考えたことが理由としては大きいです。
実際、CSSはマジで不慣れなので、いろんな人が実際に TailwindCSS でコーディングしたものを参考にさせていただきました🙇♂️
また、ドキュメントが個人的には網羅的でとても参照しやすく、細かな調整をする際にとても有用でした。
https://tailwindcss.com/docs/installation
daisyUI
スタイルにおいて一番不安に思っていたのが、サイト全体の色使いでした。
つまり、全体で統一感を持った『テーマ』を設定したいと思いました。そんな中でいくつか調査していたときに、daisyUI を見つけました。いくつかコンポーネントの実装も用意されており、参考にさせていただいた点も多々ありましたが、一番の採用理由は『テーマがかわいい』ことでした。
https://daisyui.com/docs/themes/
結局使ったのは現状2つのテーマだけなのですが、実装の際にはいろんなテーマを試しながら試行錯誤をできたのでとても楽しかったです。
また、手間をかけずにサイト全体の統一感を出せたことは個人的にはとても大きなことでした。
シークレット記事機能
これは今回のブログ記事で実装した唯一の動的な機能になります。
要は「特定の記事だけ認証を突破したユーザーにだけ公開したい」という要件を実現したいと考えました。というか、僕だけが見れる記事を執筆できるようにしたかったんです。
たまにはあまり人には見せられないような、でも自分的には書き残して後で振り返りたいような記事を書くことがあると思ったんです。というか、1本目の記事がそうだったんです。なので、必要最低限の機能でリリースして運用したいと考えました。
基本的には僕が閲覧するだけなので簡潔な実装をしたいと考えました。また、Cloudflare Pages が Let's Encrypt を利用して SSL/TLS 通信を勝手に実現してくれているので、今回は単に Basic 認証で実現することにしました。
もちろん、HTML/CSS/Javascript の静的コンテンツだけでは実現できません。サーバー側でコードを走らせる必要があります。
そこで、この機能のために Cloudflare Pages Functions を利用しました。Cloudflare Pages Functions には Middleware という機能があります。これは、特定のリクエストパスにアクセスがあったときに、そのリクエストが処理される前に呼び出されるようなロジックを定義できる機能になります。
通常の記事のパスは/articles/{article-id}
なのですが、シークレット記事は/articles/secret/{article-id}
とする設計にしました。
なので、シークレット記事のパスに該当するようなリクエストがあった時だけ、Cloudflare Pages Functions で Basic 認証のロジックを動かすことで、今回の機能を簡素に実現することができました。
ここについて注意点は、きちんと必要なリクエストパスの時だけ Cloudflare Pages Functions を呼ぶようにルーティングをきちんと設定することです。
Cloudflare Pages は無料でもほとんど無限に使うことができますが、Functions は呼び出し回数にある程度制限があります(と言っても、こんな無名なブログでは攻撃を受けない限り到達するわけないですが)。なので、無駄に呼び出し回数を増やさないような工夫をすることが望ましいと考えます。
記事がシークレットなのかどうかは、microCMS 側で1つ追加のフィールドを用意するだけで済んだので、その意味でも microCMS を導入したのは良かったです。記事のメタデータ的なものもうまく管理することができました。ビルド時の API 呼び出しでのフィルタリングなどもバッチリです。
今後について
とりあえず記事を書く体験を早く始めていきたいと考えたので、ブログの実装自体は非常に簡素です。なので、まだ実装したい機能がぼちぼちあります。
今時点で認識している課題は GitHub Issues にリストアップしているので、徐々にこの辺り改善して良い個人ブログライフを作っていきたいと思います。