MosslogMosslog
ブログサイト作ってみた(技術選定編)

ブログサイト作ってみた(技術選定編)

読了時間: 38

はじめに

前回の記事で、このブログサイトの機能実装について書きました。 今回は、なぜその技術を選んだかという視点から、技術スタックの選定理由についてまとめます。

個人開発での技術選定は、実用性と学びのバランスを取る必要があります。 このプロジェクトでは、実際に動くものを作りながら、新しい技術も学びたいという想いがありました。 そのため、単に「流行っているから」ではなく、「なぜその技術がこのプロジェクトに適しているか」を考えて選定しました。

この記事では、主要な技術選定について、選んだ理由と他の選択肢との比較をまとめます。 同じように技術選定で迷っている人の参考になればと思います。


フロントエンドフレームワーク選定

Next.js 15 を選んだ理由

フロントエンドフレームワークとして、Next.js 15を選びました。 理由はいくつかありますが、主なポイントは以下の通りです。

App Router の採用理由

Next.js 15 では、App Router(appディレクトリ)がデフォルトになっています。 これまでの Pages Router(pagesディレクトリ)と比べて、以下の点が魅力的でした。

  • ファイルベースルーティング: ファイル構成がそのまま URL 構造になるため、直感的
  • レイアウトの共有: layout.tsxで共通レイアウトを管理できる
  • ローディング状態: loading.tsxでローディング UI を簡単に実装できる
  • エラーハンドリング: error.tsxでエラー境界を設定できる

特に、ブログサイトのようなコンテンツ中心のサイトでは、ファイルベースルーティングが相性が良いと感じました。 記事一覧(/articles)や記事詳細(/articles/[id])を、ディレクトリ構造で自然に表現できます。

React Server Components の活用

Next.js 15 では、React Server Components(RSC)がデフォルトで使えます。 これにより、サーバー側でデータを取得してレンダリングできるため、クライアント側の JavaScript バンドルサイズを削減できます。

ブログサイトの場合、記事データはサーバー側で取得するのが自然です。 RSC を使うことで、初期表示が速くなり、SEO も改善されます。

SSR/SSG/ISR の使い分け

Next.js では、ページごとにレンダリング方式を選べます。

  • SSR(Server-Side Rendering): リクエストごとにサーバーでレンダリング(動的なコンテンツ向け)
  • SSG(Static Site Generation): ビルド時に静的 HTML を生成(更新頻度が低いコンテンツ向け)
  • ISR(Incremental Static Regeneration): 静的生成 + 定期的な再生成

このブログサイトでは、記事は動的に追加・更新されるため、SSR を使っています。 将来的に記事数が増えたら、ISR を検討することも考えています。

他の選択肢との比較

Next.js を選ぶ前に、他のフレームワークも検討しました。

Remix との比較

Remix もサーバーサイドレンダリングに優れたフレームワークですが、以下の理由で Next.js を選びました。

  • エコシステムの充実: Next.js の方が、ライブラリやドキュメントが充実している
  • Cloudflare Workers 対応: OpenNext を使えば、Next.js を Cloudflare Workers にデプロイできる
  • 学習コスト: より多くの情報が存在するため、学習しやすい

Astro との比較

Astro は、コンテンツ中心のサイトに適したフレームワークですが、以下の理由で Next.js を選びました:

  • React の経験: 既に React を使っていたため、Next.js の方が学習コストが低い
  • 動的な機能: 管理画面など、動的な機能も必要だったため
  • フレームワークの成熟度: Next.js の方が、機能が充実している

SvelteKit との比較

SvelteKit も軽量で魅力的ですが、以下の理由で Next.js を選びました。

  • React の経験: 既存の知識を活かせる
  • エコシステム: React の方が、コンポーネントライブラリなどが充実している
  • 仕事との関係: React/Next.js の経験が、将来的にも役立つ可能性がある

TypeScript 採用の理由

TypeScript を採用した理由は、型安全性の重要性を感じていたからです。

個人開発でも、型安全性は開発速度を上げてくれます。 特に、API のレスポンス型や、コンポーネントの props 型を定義することで、バグを減らせます。


スタイリング選定

Tailwind CSS を選んだ理由

スタイリングには、Tailwind CSSを選びました。理由は以下の通りです。

ユーティリティファーストの利点

Tailwind CSS は、ユーティリティクラスを使ってスタイリングする方式です。 例えば、text-centerで中央揃え、bg-blue-500で背景色を指定します。

この方式の利点は、CSS ファイルを書かずにスタイリングできることです。 HTML とスタイルが同じ場所にあるため、コードの見通しが良くなります。

また、デザインシステムと相性が良く、一貫したスタイリングがしやすいです。

デザインシステムとの相性

ブログサイトでは、統一感のあるデザインが重要です。Tailwind CSS では、テーマ設定でカラーパレットやスペーシングを一括管理できるため、デザインシステムを構築しやすくなります。

このブログサイトでも、カスタムカラー(ブランドカラー)を定義して、一貫したデザインを実現しています。

パフォーマンス面の考慮

Tailwind CSS は、使用されているクラスのみを CSS ファイルに含めるため、未使用の CSS が生成されません。そのため、バンドルサイズが小さくなり、パフォーマンスが向上します。

他の選択肢との比較

Tailwind CSS を選ぶ前に、他のスタイリング方法も検討しました。

CSS Modules との比較

CSS Modules は、スコープが限られた CSS を書く方式ですが、以下の理由で Tailwind CSS を選びました。

  • 開発速度: ユーティリティクラスを使う方が、スタイリングが速い
  • デザインシステム: Tailwind CSS の方が、デザインシステムと相性が良い
  • 保守性: CSS ファイルを書かなくて済むため、保守が楽

styled-components との比較

styled-components は、CSS-in-JS のライブラリですが、以下の理由で Tailwind CSS を選びました。

  • パフォーマンス: ランタイムでスタイルを生成しないため、パフォーマンスが良い
  • バンドルサイズ: ユーティリティクラスの方が、バンドルサイズが小さい
  • 開発体験: ユーティリティクラスの方が、スタイリングが速い

Emotion との比較

Emotion も CSS-in-JS のライブラリですが、上記と同じ理由で Tailwind CSS を選びました。


バックエンド・インフラ選定

Cloudflare Workers を選んだ理由

バックエンド・インフラには、Cloudflare Workersを選びました。理由は以下の通りです。

Edge Computing の利点

Cloudflare Workers は、エッジコンピューティングプラットフォームです。 エッジとは、ユーザーに近い場所でコードを実行する仕組みです。

これにより、以下の利点があります。

  • 低レイテンシ: ユーザーに近い場所で実行されるため、レスポンスが速い
  • グローバルな配信: 世界中にエッジサーバーがあるため、どこからでも速くアクセスできる
  • サーバーレス: サーバーの管理が不要で、スケールも自動的

ブログサイトの場合、世界中のユーザーがアクセスする可能性があるため、エッジコンピューティングが相性が良いと考えました。

サーバーレスアーキテクチャの採用

サーバーレスアーキテクチャを採用することで、以下の利点があります。

  • 運用の簡素化: サーバーの管理が不要
  • コストパフォーマンス: 使った分だけ課金される
  • スケーラビリティ: 自動的にスケールするため、トラフィックが増えても対応できる

個人開発では、運用コストを抑えたいため、サーバーレスが適していました。

コストパフォーマンス

Cloudflare Workers には無料プランがあり、個人ブログであれば十分なリクエスト数が含まれています(詳細は公式サイトで確認してください)。

個人ブログであれば、無料プランで十分な場合が多いです。 また、他の Cloudflare サービス(D1、R2)と統合しやすい点も魅力的でした。 有料プランも比較的低価格で、必要に応じてアップグレードできる点も良かったです。

Cloudflare D1 を選んだ理由

データベースには、Cloudflare D1を選びました。D1 は、SQLite ベースのデータベースです。

個人ブログのような小規模なサイトには、SQLite で十分です。 また、開発環境でもローカルで SQLite を使えるため、開発が楽です。

エッジでのデータベースアクセス

D1 は、Cloudflare Workers から直接アクセスできるため、エッジからデータベースにアクセスできます。これにより、レイテンシが削減されます。

ただし、D1 は現時点では単一リージョンでの運用です。将来的には、エッジでの読み取りレプリカも検討されているようです。

コスト面の優位性

D1 には無料プランがあり、個人ブログであれば十分なリソースが含まれています(具体的な制限は公式サイトで確認してください)。

個人ブログであれば、無料プランで十分です。記事データやタグ情報程度であれば、無料プランの範囲内で運用できるでしょう。

他の選択肢との比較

D1 を選ぶ前に、他のデータベースも検討しました。

PostgreSQL/MySQL との比較

PostgreSQL や MySQL は、より高機能なデータベースですが、以下の理由で D1 を選びました。

  • 運用の簡素化: サーバーの管理が不要
  • コスト: 無料プランがある
  • 統合性: Cloudflare Workers と統合しやすい

Cloudflare R2 を選んだ理由

画像ストレージには、Cloudflare R2を選びました。R2 は、S3 互換のオブジェクトストレージです。

S3 互換 API

R2 は、AWS S3 と互換の API を持っているため、S3 用のライブラリがそのまま使えます。 例えば、@aws-sdk/client-s3@aws-sdk/s3-request-presignerが使えます。

既存の知識やライブラリを活かせる点が魅力的でした。

エグレス費用なし

R2 の最大の利点は、エグレス費用がかからないことです。S3 では、データの転送量に応じてエグレス費用がかかりますが、R2 では無料です。

ブログサイトの場合、画像を頻繁に読み込むため、エグレス費用がかさむ可能性があります。R2 を使うことで、コストを抑えられます。

画像ストレージとしての採用

R2 は、画像などの静的ファイルを保存するのに適しています。Presigned URL を使えば、セキュアにアップロードできます。


認証・セキュリティ選定

Cloudflare Access + JWT を選んだ理由

認証には、Cloudflare Access + JWTを選びました。理由は以下の通りです。

シンプルな認証フロー

Cloudflare Access を使うと、管理画面へのアクセスを簡単に制限できます。 JWT トークンを使って認証し、Cloudflare Workers 側で検証します。

個人ブログの場合、管理者は自分だけなので、複雑な認証システムは不要でした。シンプルな認証フローで十分です。

Zero Trust アーキテクチャ

Cloudflare Access は、Zero Trust アーキテクチャを採用しています。 Zero Trust とは、「信頼しない、常に検証する」という考え方です。

すべてのリクエストを検証することで、セキュリティが向上します。

他の選択肢との比較

Cloudflare Access を選ぶ前に、他の認証方法も検討しました。

NextAuth.js との比較

NextAuth.js は、Next.js 向けの認証ライブラリですが、以下の理由で Cloudflare Access を選びました。

  • シンプルさ: 個人ブログには、シンプルな認証で十分
  • Cloudflare 統合: Cloudflare Workers と統合しやすい
  • コスト: 無料で使える

Auth0 との比較

Auth0 も認証サービスですが、上記と同じ理由で Cloudflare Access を選びました。


開発ツール選定

Biome を選んだ理由

リンター・フォーマッターには、Biomeを選びました。理由は以下の通りです。

高速な Lint & Format

Biome は、Rust で実装されているため、非常に高速です。ESLint + Prettier の代替として使えます。

開発体験が向上します。

単一ツールでの統合

Biome は、リンターとフォーマッターが統合されています。そのため、設定ファイルが一つで済みます。

ESLint + Prettier の場合、設定ファイルが複数必要になりますが、Biome では一つで済みます。

Vitest を選んだ理由

テストランナーには、Vitestを選びました。理由は以下の通りです。

Vite ベースの高速性

Vitest は、Vite ベースで実装されているため、非常に高速です。 Jest と比べて、テストの実行速度が速いです。

開発体験が向上します。

Jest との互換性

Vitest は、Jest と互換性があります。Jest の API がそのまま使えるため、移行が楽です。

既存のテストコードをそのまま使えます。

Playwright を選んだ理由

E2E テストには、Playwrightを選びました。理由は以下の通りです。

複数ブラウザ対応

Playwright は、Chromium、Firefox、WebKitの複数ブラウザに対応しています。 そのため、クロスブラウザテストが簡単です。

Cypress との比較

Cypress も E2E テストツールですが、以下の理由で Playwright を選びました。

  • 複数ブラウザ対応: Playwright の方が、対応ブラウザが多い
  • パフォーマンス: Playwright の方が、実行速度が速い
  • API: Playwright の API の方が、直感的

デプロイ戦略

OpenNext + Cloudflare Workers を選んだ理由

デプロイには、OpenNext + Cloudflare Workersを選びました。理由は以下の通りです。

Next.js の機能を維持

OpenNext は、Next.js アプリケーションを Cloudflare Workers にデプロイするためのツールです。 Next.js の機能(SSR、API Routes、画像最適化など)を維持しながら、Cloudflare Workers で動かせます。

Edge Runtime への最適化

OpenNext は、Edge Runtime に最適化されています。Cloudflare Workers の制約に合わせて、Next.js アプリケーションを変換します。

Vercel との比較

Vercel は、Next.js の公式デプロイプラットフォームですが、以下の理由で Cloudflare Workers を選びました。

  • コスト: 無料プランがある
  • 統合性: 他の Cloudflare サービス(D1、R2)と統合しやすい
  • 学習: Cloudflare Workers の経験を積みたい

コスト面の考慮

Cloudflare Workers には無料プランがあり、個人ブログであれば十分なリソースが含まれています(詳細は公式サイトで確認してください)。

個人ブログであれば、無料プランで十分です。実際に運用してみて、トラフィックが増えた場合に有料プランへのアップグレードを検討するという方針で問題ないかなと思います。


選定の振り返り

選定で正解だった点

技術選定を振り返ると、以下の点が良かったと思います。

  • Next.js: App Router の採用で、開発体験が向上した
  • Cloudflare Workers: エッジコンピューティングにより、パフォーマンスが向上した
  • TypeScript: 型安全性により、バグを減らせた
  • Tailwind CSS: ユーティリティクラスにより、開発速度が向上した

選定で失敗した点

一方で、以下の点は改善の余地があったと思います。

  • D1 の制約: エッジでの読み取りレプリカがないため、レイテンシが気になる場合がある
  • OpenNext の制約: 一部の Next.js 機能(画像最適化など)が制限される

現時点では、選んだ技術スタックで十分に満足しています。


終わりに

この記事では、Mosslog の技術選定について、なぜその技術を選んだかという視点からまとめました。 個人開発での技術選定は、実用性と学びのバランスを取ることが重要です。

次回は、実際の開発で遭遇した課題と解決方法について詳しく書く予定です。 技術選定はできても、実際に使ってみると様々な課題に直面します。

同じように技術選定で迷っている人の参考になれば嬉しいです。