概要
このブログは2018年からJekyllで運営してきました。JekyllはRubyベースの静的サイトジェネレーターで、GitHub Pagesとの自然な統合のおかげで多くの開発者ブログで使用されています。
しかし、ポストが増えてプラグインが多くなるにつれてビルド速度が急激に遅くなる問題に直面し、結局2026年2月にAstroへの全面マイグレーションを決定しました。
今回の記事では、なぜJekyllからAstroに移行することになったのか、その背景と理由を共有します。
Jekyllの限界
ビルド速度の問題
Jekyllでブログを運営しながら最も大きな問題はビルド速度でした。ポストが増え、多言語(日本語/韓国語/英語)対応と様々なプラグインを使用するにつれて、ビルド時間が急激に増加しました。
bundle exec jekyll serve
上記のコマンドでローカルで記事を確認する時、209秒(約3分30秒)を待たなければならない状況になりました。以前のブログポスト(ブログプレビューを速く)でlimit_posts設定とminifyプラグインの無効化で50秒まで短縮したことがありましたが、根本的な解決策ではありませんでした。
# _config-dev.yml
limit_posts: 3
jekyll-minifier:
remove_spaces_inside_tags: false
remove_multi_spaces: false
remove_comments: false
compress_css: false
compress_javascript: false
compress_json: false
このように設定しても50秒という時間がかかり、記事を修正するたびにこの時間を待たなければなりませんでした。
Ruby依存性管理の難しさ
JekyllはRubyベースのため、Rubyバージョン管理、Bundler、Gem依存性などを一緒に管理する必要があります。フロントエンド開発者として日常的に使用するNode.js/npmエコシステムとは別の環境を維持するのは面倒なことでした。
Liquidテンプレートの限界
JekyllのLiquidテンプレートエンジンはシンプルなブログには十分ですが、複雑なロジックやコンポーネントの再利用が必要な場合には制限的です。特に多言語対応、動的メタタグ、構造化データ(JSON-LD)などを実装する時にコードが複雑になる傾向がありました。
代替案の検討
Jekyllから離れることを決めた後、複数の静的サイトジェネレーターを検討しました。
Hugo
- 長所:Goベースでビルド速度が非常に速い
- 短所:Goテンプレート文法が直感的ではなく、フロントエンドエコシステムとの統合が制限的
Gatsby
- 長所:Reactベース、豊富なプラグインエコシステム
- 短所:GraphQL学習が必要、ビルド時間がプロジェクト規模に比例して遅くなる、エコシステムの活発さが低下
Next.js
- 長所:Reactベース、サーバーサイドレンダリング(SSR)対応、活発なエコシステム
- 短所:ブログには過度な機能、静的サイト用としては設定が複雑、不必要なJavaScriptバンドル
Astro
- 長所:Zero JS by default、Viteベースの高速開発サーバー、Content Collections、マークダウン中心、様々なフレームワーク統合可能
- 短所:比較的新しいフレームワーク(ただし活発なコミュニティ)
Astroを選んだ理由
複数の代替案を検討した結果、Astroがこのブログの要件に最も適していると判断しました。
1. Zero JavaScript by Default
Astroは基本的にクライアントにJavaScriptを送信しません。ブログはほとんどが静的コンテンツなので、不必要なJavaScriptバンドルなしに純粋なHTML/CSSだけで高速にロードされるのが理想的です。
2. Viteベースの高速開発サーバー
Viteを基盤とした開発サーバーはHMR(Hot Module Replacement)をサポートしており、ファイルを修正するとすぐにブラウザに反映されます。Jekyllで50〜209秒を待っていたのと比べると革新的な改善です。
3. Content Collections
ブログポストを作成する時、各マークダウンファイルの上部にはタイトル、説明、日付などのメタ情報(frontmatter)を記述します。Jekyllではこの情報にタイプミスがあったり必須項目が抜けていてもビルドがそのまま進行し、デプロイ後に問題を発見することがありました。
AstroのContent Collectionsはこの問題を解決してくれます。各フィールドのタイプ(文字列、日付、ブーリアンなど)と必須かどうかを事前に定義しておくと、ビルド時に自動的に検証して間違ったデータがあればエラーとして知らせてくれます。この検証ルールを定義するのにZodというTypeScript検証ライブラリを使用します。
例えば、以下のように「ブログポストには必ずtitle(文字列)、lang(ja/ko/enのいずれか)、date(日付)などが必要」と定義できます。
const blog = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content' }),
schema: z.object({
title: z.string(), // 必須、文字列
description: z.string(), // 必須、文字列
lang: z.enum(['ja', 'ko', 'en']), // 必須、3つのうち1つ
category: z.string(), // 必須、文字列
permalink: z.string(), // 必須、文字列
date: z.coerce.date(), // 必須、日付
// ...
}),
});
もしマークダウンファイルでtitleを書き忘れたり、langに'kr'のような間違った値を入れるとビルドが失敗し、どのファイルのどのフィールドが間違っているのか正確に教えてくれます。おかげでミスをデプロイ前に事前にキャッチできます。
4. マークダウン中心のワークフロー
既存のJekyllブログのマークダウンファイルをほぼそのまま使用できました。rehype/remarkプラグインを通じてマークダウン処理を細かくカスタマイズできる点も大きな利点です。
5. Node.jsエコシステム
npmですべての依存性を管理するため、Ruby/Bundlerを別途管理する必要がありません。フロントエンド開発者にとって馴染みのある環境でブログを運営できます。
マイグレーション結果
ビルド時間の比較
マイグレーションの最大の動機であったビルド速度から見ていきましょう。
| 項目 | Jekyll | Astro |
|---|---|---|
| フルビルド | ~209秒 | ~30秒 |
| 開発サーバー起動 | ~50秒(最適化後) | ~2秒 |
| ファイル変更の反映 | 全体リビルドが必要 | HMR即時反映 |
フルビルド時間が209秒から30秒へ、約7倍速くなりました。しかし体感上最も大きな変化は開発サーバーです。Jekyllでは記事1つを修正して確認するのに最低50秒を待たなければなりませんでしたが、Astroでは保存した瞬間にブラウザに反映されます。記事を書く流れが途切れなくなったのが最も満足している部分です。
主な改善点
ビルド速度以外にもAstroに移行して多くの部分が改善されました。
- ビルド速度:上記で見た通り、フルビルドと開発サーバーの両方が劇的に速くなりました。
- 開発体験:
ViteベースのHMRのおかげで、コードを修正するとブラウザが即座に更新されます。リロードさえ不要な場合がほとんどです。 - 型安全性:
Content CollectionsのZodスキーマ検証により、frontmatterにタイプミスがあったり必須フィールドが抜けているとビルド段階ですぐにエラーを教えてくれます。デプロイ後に問題を発見することがなくなりました。 - 画像最適化:
Sharpを利用したカスタムプラグインで画像をAVIF/WebP形式に自動変換します。手作業なしにビルド時に自動で最適化された画像が生成されます。 - 検索機能:
Pagefindを導入してサーバーなしでも高速な全文検索が可能になりました。JekyllではJSONファイルベースの遅い検索を使用していました。 - コードハイライト:
Shikiを利用したサーバーサイドコードハイライトにより、別途CSSなしでもVS Codeレベルの正確なシンタックスハイライトが適用されます。
私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!
アプリ広報
Dekuが開発したアプリを使ってみてください。Dekuが開発したアプリはFlutterで開発されています。興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。