技術記事 なぜAstro.jsを選んだのか - Tech Blog構築の技術選定

なぜAstro.jsを選んだのか - Tech Blog構築の技術選定

はじめに

おもしろテクノロジーのTech Blogを立ち上げるにあたり、技術スタックの選定は最も重要な判断の一つでした。この記事では、なぜ私たちがAstro.jsを選んだのか、その背景と判断基準を共有します。


前提: Tech Blogに求めたもの

まず、私たちがTech Blogに求めた要件を整理します。

1. パフォーマンス

  • ページ読み込み速度の高速化
  • SEO最適化
  • Core Web Vitalsの高スコア

2. コンテンツ管理の柔軟性

  • マークダウンでの執筆
  • ヘッドレスCMSとの連携
  • バージョン管理

3. 開発体験

4. 拡張性

  • インタラクティブなUI要素の追加
  • 将来的な機能拡張に対応

5. 運用コスト

  • ホスティングコストの最小化
  • メンテナンス負荷の軽減

技術選定の候補

検討した主な候補は以下の通りです。

Frameworkメリットデメリット
Next.jsReactエコシステム、豊富な実績、Vercel最適化JavaScriptバンドルサイズ大、オーバースペック
Gatsby静的サイト生成、プラグイン豊富ビルド時間長い、React依存
Astro.jsゼロJSデフォルト、柔軟なフレームワーク選択、高速比較的新しい、日本語情報少ない
Hugo超高速ビルド、シンプルGo言語、拡張性に限界
Nuxt.jsVueエコシステム、SSG/SSR両対応Vue学習コスト、バンドルサイズ

なぜAstro.jsなのか

1. ゼロJavaScriptのデフォルト哲学

Astro.jsの最大の特徴は「デフォルトでJavaScriptを送信しない」という哲学です。

---
// サーバーサイドで実行されるコード
const posts = await getPosts();
---

<div>
  {posts.map(post => (
    <article>
      <h2>{post.title}</h2>
      <p>{post.excerpt}</p>
    </article>
  ))}
</div>

上記のコードは完全に静的HTMLとしてレンダリングされ、クライアントにJavaScriptは送られません。

Tech Blogのようなコンテンツ中心のサイトにおいて、これは劇的なパフォーマンス向上をもたらします。

パフォーマンスベンチマーク(想定値)
MetricAstro.jsNext.js SSGGatsby
First Contentful Paint0.8s1.2s1.5s
Time to Interactive1.0s2.5s3.0s
Total Bundle Size10KB150KB200KB

2. Islands Architecture

Astro.jsの「Islands Architecture」は、必要な部分だけをインタラクティブにできます。

---
import SearchBox from '../components/SearchBox.tsx';
import GraphVisualization from '../components/GraphVisualization.tsx';
---

<!-- 静的コンテンツ -->
<header>
  <h1>おもしろテクノロジー Tech Blog</h1>
</header>

<!-- インタラクティブな島 -->
<SearchBox client:load />

<!-- 記事リスト(静的) -->
<article>...</article>

<!-- インタラクティブな島(ビューポート内で遅延読み込み) -->
<GraphVisualization client:visible />
Islands Architectureのメリット
  1. 選択的ハイドレーション: 必要なコンポーネントだけをハイドレート
  2. フレームワーク混在: React、Vue、Svelte等を同一ページで使用可能
  3. パフォーマンス最適化: ユーザーが見ている部分だけを優先的に読み込み

3. フレームワーク非依存

Astro.jsは特定のUIフレームワークに縛られません。

---
import ReactComponent from './ReactComponent.tsx';
import VueComponent from './VueComponent.vue';
import SvelteComponent from './SvelteComponent.svelte';
---

<!-- すべて同じページで使える -->
<ReactComponent client:load />
<VueComponent client:visible />
<SvelteComponent client:idle />

私たちはReactの豊富なエコシステムを活用しつつ、将来的に他のフレームワークも選択できる柔軟性を確保しました。


4. 開発体験の良さ

TypeScript完全サポート
// src/types/post.ts
export interface Post {
  title: string;
  slug: string;
  category: 'tech' | 'interview' | 'philosophy';
  publishedAt: Date;
  tags: string[];
}

// src/pages/articles/[slug].astro
---
import type { Post } from '../../types/post';

export async function getStaticPaths() {
  const posts = await getPosts();
  return posts.map((post: Post) => ({
    params: { slug: post.slug },
    props: { post }
  }));
}

const { post } = Astro.props;
---

型安全性を保ちながら、快適に開発できます。

Hot Module Replacement (HMR)

Viteベースのため、高速なHMRで開発体験が快適です。


5. microCMSとの相性

ヘッドレスCMSとの連携が非常にシンプルです。

// src/lib/microcms.ts
import { createClient } from 'microcms-js-sdk';

const client = createClient({
  serviceDomain: import.meta.env.MICROCMS_SERVICE_DOMAIN,
  apiKey: import.meta.env.MICROCMS_API_KEY,
});

export async function getPosts() {
  const { contents } = await client.get({
    endpoint: 'articles',
  });
  return contents;
}
---
import { getPosts } from '../lib/microcms';

const posts = await getPosts();
---

<div>
  {posts.map(post => (
    <article>
      <h2>{post.title}</h2>
      <div set:html={post.body} />
    </article>
  ))}
</div>

ビルド時に全記事を取得し、完全な静的サイトを生成します。


比較: なぜNext.jsではないのか

Next.jsは素晴らしいフレームワークですが、Tech Blogには過剰でした。

Next.jsが優れている場面

  • 動的なルーティングが多い
  • サーバーサイドレンダリング(SSR)が必要
  • Vercelのエッジ機能を活用したい

Astro.jsが優れている場面(私たちのケース)

  • コンテンツが静的
  • ビルド時に全データが確定
  • JavaScriptを最小限に抑えたい

パフォーマンス比較

同じブログサイトをNext.js(SSG)とAstro.jsで構築した場合の想定値:

指標Next.jsAstro.js差分
初期JavaScriptサイズ120KB5KB-96%
Time to Interactive2.3s0.9s-61%
Lighthouse Score92100+8

技術スタック全体像

最終的に採用した技術スタックは以下の通りです。

┌─────────────────────────────────────┐
│         Presentation Layer          │
│        Astro.js + React             │
│    (Islands Architecture)           │
└──────────────┬──────────────────────┘


┌─────────────────────────────────────┐
│         Content Layer               │
│        microCMS (Headless CMS)      │
└──────────────┬──────────────────────┘


┌─────────────────────────────────────┐
│         Styling & Animation         │
│    Tailwind CSS + Framer Motion     │
└─────────────────────────────────────┘


┌─────────────────────────────────────┐
│         Deployment                  │
│    Cloudflare Pages / Vercel        │
└─────────────────────────────────────┘

各レイヤーの役割

  1. Presentation Layer (Astro.js + React)

    • 静的サイト生成
    • インタラクティブ要素はReact Islands
  2. Content Layer (microCMS)

    • 記事管理
    • APIベースのコンテンツ配信
    • 無料枠で十分な範囲
  3. Styling & Animation

    • Tailwind CSS: ユーティリティファーストでデザインシステム構築
    • Framer Motion: スムーズなアニメーション
  4. Deployment

    • Cloudflare Pages: 高速CDN、無料枠が広い
    • または Vercel: Astro最適化

実装上の工夫

1. サムネイル自動生成

OG画像を動的生成し、シェア時の見栄えを向上させます。

// src/pages/og/[slug].png.ts
import satori from 'satori';
import { html } from 'satori-html';

export async function GET({ params }) {
  const post = await getPost(params.slug);

  const markup = html`
    <div style="background: linear-gradient(135deg, #000 0%, #1a1a2e 100%);
                width: 1200px; height: 630px;
                display: flex; align-items: center; justify-content: center;">
      <h1 style="color: #fff; font-size: 64px;">
        ${post.title}
      </h1>
    </div>
  `;

  const svg = await satori(markup, { width: 1200, height: 630 });
  // SVG to PNG conversion
  return new Response(png, { headers: { 'Content-Type': 'image/png' } });
}

2. Pagefind統合による高速検索

---
// src/components/SearchBox.astro
---

<div id="search"></div>

<script>
  import * as pagefind from 'pagefind';

  pagefind.init();
  pagefind.search('Astro.js').then(results => {
    console.log(results);
  });
  </script>

ビルド時にインデックスを生成し、クライアント側で高速に検索できます。


失敗と学び

失敗1: 最初はGatsbyを検討した

当初、Gatsbyを候補に挙げていました。

問題点:

  • ビルド時間が記事数に比例して長くなる
  • GraphQLの学習コスト
  • プラグインの依存関係管理が複雑

学び: シンプルさを優先すべきだった。Astro.jsは必要最小限の抽象化で、理解しやすい。

失敗2: 全てを静的にしようとした

最初は「完全静的サイト」を目指しましたが、検索機能やGraph UIでインタラクションが必要でした。

解決策: Islands Architectureを活用し、必要な部分だけをインタラクティブに。

学び: 完璧を目指すより、段階的に改善する方が現実的。


まとめ

Astro.jsを選んだ理由は以下の3点に集約されます。

  1. パフォーマンス最優先: ゼロJSデフォルトで超高速
  2. 柔軟性: Islands Architectureとフレームワーク非依存
  3. シンプルさ: 必要最小限の抽象化で理解しやすい

Tech Blogのようなコンテンツ中心のサイトにおいて、Astro.jsは最適な選択肢です。


次のステップ

  • トップページワイヤーフレーム制作
  • Astro + microCMS初期構築
  • サムネ自動生成実装
  • 初期記事10本執筆

次回の記事では、Astro.js + microCMSの実装詳細を共有します。


参考リンク


著者について

株式会社おもしろテクノロジー 岩手を拠点に、AI×製造×地方創生に取り組むテクノロジー企業

技術で社会をおもしろくする。


この記事が役立ったら、シェアしていただけると嬉しいです。

Ibuki Noro 代表取締役
おもしろテクノロジーの代表取締役をしています。音楽が好き