EN

このサイトをAstro + Vercel + Cloudflareで組んだ理由

このサイトはサーバーを1台も借りていません。ランニングコストはドメイン代だけで、独自ドメイン・HTTPS・問い合わせフォーム・contact@でのメール受信・日英対応・RSSまで動いています。

構成を決めるとき、選定の記録はADRとして残しました。この記事はその要約にあたります。「何を使ったか」ではなく「なぜそれを選ばなかったか」のほうに紙面を割きます。

この記事の内容は次のとおりです。

前提

先に条件を書きます。判断はここから逆算しています。

  • 目的は案件獲得。企業の担当者にURLを送る使い方が中心になる
  • 記事はMarkdownで管理する。CMSは入れない
  • 4画面(Home / Posts / Work / About)+ 記事詳細
  • 英語版を後から足す。海外案件も対象に入れているため
  • 更新頻度は低い。ビルド時間より「書くまでの手数の少なさ」を優先する
  • 動くのはテーマ切替とスクロール進捗バーの2箇所だけ

そして、いちばん効いた前提がこれです。

個人プロジェクトでは自分の作業時間が唯一の希少資源。

無料かどうかより先に、この軸で選んでいます。

Astroを選んだ理由

比較の軸は「候補が後続作業をどれだけ肩代わりしてくれるか」に置きました。標準機能で済む範囲が広いほど、完成に近づくためです。

後続の作業AstroNext.jsHugo
frontmatterの型付けContent Collections + Zodで標準自前型の概念なし
コード配色のライト/ダーク両対応Shikiのデュアルテーマ標準自前設定両対応は手作業
i18nネイティブルーティングApp Routerでは自前対応あり、設定は独特
RSS / sitemap公式インテグレーションsitemapのみ標準
JS出力デフォルト0ランタイム込み0

デザインが要求する動きが2箇所しかないのに、フレームワークのランタイムを全ページに常時載せる理由がありません。AstroはデフォルトでJSを出力せず、必要な2箇所だけを島にできます。

なぜNext.jsにしなかったか

React / Next.jsの実務経験がそのまま活きる点は、唯一かつ実質的な利点でした。それでも見送ったのは2つの理由からです。

  1. 静的テキストサイトに対してランタイムが過剰
  2. 上表の4項目をすべて自前で組む必要がある

Astroのテンプレート記法はJSXに近く、島にReactをそのまま持ち込めます。乗り換えコストがこの2点を上回らないと判断しました。

なぜHugoにしなかったか

ビルド最速・単一バイナリは魅力ですが、この案件では「ビルド時間より書くまでの手数を優先する」と決めているため、その最大の利点が効きません。残るのはGoテンプレートの学習コストと、型付きfrontmatterの不在だけになります。

候補の強みが、自分の制約と噛み合うかどうか。 一般論としての優劣は判断材料になりませんでした。

Vercelを選んだ理由

動的処理が必要なのは2箇所だけでした。

  1. 問い合わせフォームの送信 — 案件相談の受け口であり、サイトの出口
  2. OG画像 — URLを送る使い方が中心なので、SlackやXでのカード表示が実質的な第一印象になる

この2箇所はどちらも目的に直結します。フォームが動かなければ案件相談は1件も来ません。 そこで「この2つの取り回しが最も楽な選択肢」を選びました。

GitHub Pagesは完全静的で、この2箇所がどちらも実現できないため落ちました。Cloudflare Pagesは有力な次点で、帯域の無料枠はVercelより大きいです。それでもVercelにしたのは、まだ発生していない帯域の問題より、実装のしやすさを優先したためです。

無料でこれだけ付いてくる

選定時は意識していませんでしたが、使ってみて驚いたのがこの範囲でした。

機能内容
CDN世界中のエッジから配信。設定不要
HTTPS証明書ドメインを追加すると自動発行。更新も自動
DDoS対策L3 / L4 / L7を全プランで自動的に緩和。設定不要
Attack Mode攻撃時に全アクセスへチャレンジを課す。全プラン無料
WAFIPブロックとカスタムルールが各3つまで
プレビューデプロイPRごとに本番同等のURLが生えてくる

とくにDDoS対策は、公式ドキュメントにこう書かれています。

Vercel provides automatic DDoS mitigation for all deployments, regardless of your plan.

Vercel does not charge customers for traffic that gets blocked with DDoS mitigation.

ブロックした分の課金もされません。 個人サイトでDDoSを食らう確率は高くありませんが、「食らったら破産する」という不安を持たずに公開できるのは大きいと感じました。

証明書の自動更新も地味に効きます。Let’s Encryptの更新をcronで回して、失敗に気づかず期限切れ——という定番の事故が、構造的に起きません。

プレビューデプロイが一番効いた

PRを作ると、その変更だけが反映されたURLが自動で生えてきます。ローカルで動いても本番で壊れることはあるので、マージ前に本番同等の環境で確認できるのは想像以上に効きました。

実際、CSPの設定ミスでフォーム送信が止まる不具合を、この仕組みで本番前に見つけています。

Cloudflareを選んだ理由

ドメインはCloudflare Registrarで取り、DNSもCloudflareに置いています。理由は3つです。

1.原価販売で、更新時に値上げされない

ドメインは一度配ると変えられません。名刺・スキルシート・過去記事の被リンクに乗るので、10年単位で持つ前提になります。多くのレジストラは初年度を安くして翌年から上げますが、Cloudflareは原価で売る方針を明示しています。長期保有の前提と直接噛み合いました。

2. Whois代行が標準で無料

登録者の氏名がDATA REDACTEDとして秘匿されます。個人でドメインを持つとき、ここが有料オプションだと地味に効いてきます。

3. DNSを同じ管理画面に置ける

配信はVercel、DNSはCloudflareという2箇所構成にはなりますが、ドメイン・DNS・メールが1箇所にまとまります。

Email Routingが無料だった

contact@yomaru-tech.com宛のメールを普段使いのGmailに転送しています。Cloudflare Email Routingが無料で、MX / SPF / DKIMのレコードも自動で入ります。

個人サイトで独自ドメインのメールを持とうとすると、従来はGoogle Workspaceを契約するのが定番でした。受信だけでいいなら無料で済みます。

ただし受信専用で、contact@から送る機能はありません。返信すると差出人はGmailのアドレスになります。ここは割り切っています。

引き受けたトレードオフ

良かった話だけ書くと嘘になるので、選定時に飲んだ不利益も並べます。

  • Vercelの帯域の無料枠はCloudflareより小さい。記事がバズると上限に触れ得る
  • 管理画面が2箇所に分かれる。ドメインとメールはCloudflare、デプロイはVercel
  • ドメイン名にハイフンが入る(yomaru-tech.com)。口頭で伝えるとき「ハイフン」を明示する必要があり、書き写されるときに落ちる。第一候補のyomaru.com / yomaru.devはどちらも取得済みだった
  • AstroのエコシステムはReactほど広くない。凝ったUIが必要になったとき選択肢が少ない

無料プランの利用規約は読んでおく

これは公開後に気づいた点です。VercelのHobbyプランはドキュメントに明記されています。

the Hobby plan restricts users to non-commercial, personal use only.

個人のポートフォリオやブログ自体は通常問題になりませんが、能動的に仕事を募集しているサイトがどう判断されるかは微妙なところがあります。名刺に載せたURLが止まると影響が大きいので、無料枠に乗るときは規約の範囲を確認しておいたほうがいいです。

「無料で使える幸せ」を書いた直後にこれを書くのは据わりが悪いのですが、条件を確認せずに乗るのは幸せではなく運なので、正直に書いておきます。

まとめ

  • Astro — 動きが2箇所しかないなら、JSを出さないのがいちばん速い
  • Vercel — CDN・HTTPS・DDoS対策・プレビュー環境が、設定ゼロで無料で付いてくる
  • Cloudflare — 長期保有するドメインは、原価販売とWhois代行が効く。メール受信も無料

個人開発で使える無料枠は、10年前なら月額数万円を払って手に入れていた水準にあります。証明書の自動更新も、世界規模のCDNも、L7のDDoS対策も、設定なしで付いてきます。

そのうえで、無料だから選ぶのではなく、制約と噛み合うから選ぶという順序は守りたいと思っています。ここに挙げた選択はどれも、無料であることより先に「自分の作業時間をどれだけ肩代わりしてくれるか」で決めました。結果として無料だった、というだけの話でもあります。