Astro 6.0安定版がリリースされたのでこのブログの移行要否を調べた
このブログはAstro 5系(現在^5.16.8)で動いている。3月10日にAstro 6.0の安定版がリリースされたので、何が変わったのか、移行するなら何をやる必要があるのか調べた。
Astro 6の主要な新機能
開発サーバの再設計(Vite Environment API)
astro devがViteのEnvironment APIを使って完全に作り直された。これにより、開発時に本番と同じランタイムでコードを実行できるようになった。
一番恩恵が大きいのはCloudflare Workersユーザーで、開発中にKV、D1、R2、Durable Objectsなどのバインディングに直接アクセスできる。このブログはVercelにデプロイしているので直接の恩恵は薄いが、「ローカルでは動くのにデプロイすると壊れる」系の問題が減る方向性は歓迎。
Fonts API
カスタムフォントの管理を自動化するAPIが追加された。
import { defineConfig, fontProviders } from 'astro/config';
export default defineConfig({
fonts: [{
name: 'Roboto',
cssVariable: '--font-roboto',
provider: fontProviders.fontsource(),
}],
});
コンポーネント側では<Font>コンポーネントでプリロードを指示できる。
---
import { Font } from 'astro:assets';
---
<Font cssVariable="--font-roboto" preload />
フォントのダウンロード・キャッシュ・セルフホスティング・フォールバック生成・プリロードリンクの挿入を全部やってくれる。Google Fonts、Fontsource、Bunnyなど複数のプロバイダに対応している。
Content Security Policy(CSP)
Astro 5で実験的だったCSPサポートが安定版に昇格。静的ページ・動的ページの両方で、サーバー・サーバーレス環境を問わず使える。
export default defineConfig({
security: {
csp: {
algorithm: 'SHA-512',
directives: ["default-src 'self'"],
},
},
});
フレームワークがすべてのスクリプトとスタイルを自動的にハッシュ化してくれる。JavaScriptメタフレームワークで組み込みCSPを提供するのはAstroが初。
Live Content Collections
Astro 5.10で実験的に導入されたLive Content Collectionsが安定版に。ビルド時ではなくリクエスト時にコンテンツを取得できる。
import { defineLiveCollection } from 'astro:content';
const updates = defineLiveCollection({
loader: cmsLoader({ apiKey: process.env.MY_API_KEY }),
schema: z.object({ /* ... */ }),
});
CMSやAPIからのデータがリビルドなしで即座に反映される。このブログはMarkdownファイルベースなので直接は使わないが、外部CMSと連携するサイトでは便利そう。
実験的機能
Rustコンパイラ
Go製だった.astroコンパイラの後継としてRust製コンパイラが実験的に追加された。
experimental: { rustCompiler: true }
@astrojs/compiler-rsのインストールが必要。パフォーマンス向上・診断の強化・信頼性の改善が目的。
キューレンダリング
再帰的レンダリングの代わりに2パス方式を採用する実験的機能。初期ベンチマークでは最大2倍のレンダリング速度を記録しており、Astro v7でデフォルトになる予定。
experimental: {
queuedRendering: { enabled: true },
}
ルートキャッシング
Web標準のキャッシュセマンティクスを使ったプラットフォーム非依存のキャッシュAPI。ページとコンテンツエントリ間の依存関係を自動追跡する。
import { memoryCache } from 'astro/config';
export default defineConfig({
experimental: {
cache: { provider: memoryCache() },
},
});
ページ側でAstro.cache.set()を使ってキャッシュポリシーを設定できる。SSR環境で使う機能なので静的サイトには関係ないが、将来的にSSRに移行する場合は選択肢になる。
破壊的変更の一覧
Node.js 22必須
Node 18は2025年3月にEOL済み、Node 20は2026年4月にEOL予定。Astro 6はNode 22.12.0以上が必須になった。
このブログのプロジェクトはVoltaでnode: "22.22.0"を指定しているので問題なし。Vercel側のNode設定も確認が必要。
Vite 7
Astro本体と全@astrojsパッケージがVite 7に移行。カスタムでViteバージョンを固定している場合はv7以上に更新が必要。Vitestユーザーはv3.2以上が必要。
このブログはvitest: "^4.0.18"なので問題なし。
Zod 4
コンテンツスキーマのバリデーションに使われるZodがv4に。主な変更点:
| Zod 3 | Zod 4 |
|---|---|
z.string().email() | z.email() |
.min(5, { message: "..." }) | .min(5, { error: "..." }) |
.transform(Number).default("0") | .transform(Number).default(0) — defaultは変換後の型 |
Zodをastro:contentからインポートしている場合はastro/zodに変更が必要。
Shiki 4
コードハイライトのShikiがv4に。<Code />コンポーネントやMarkdownのコードブロックに影響する可能性がある。Shiki固有のAPIを直接使っている場合は移行ガイドの確認が必要。
レガシーコンテンツコレクションの廃止
Astro 5.0で導入されたContent Layer APIへの完全移行が必須になった。レガシーコレクション(type: 'content'を使うもの)はサポート外。
移行作業:
src/content/config.ts→src/content.config.tsにリネーム- コレクション定義に
loaderを追加(glob()を使用) type: 'content'の宣言を削除getEntryBySlug()→getEntry()post.slug→post.id(ファイル名はfilePath)entry.render()→render(entry)(astro:contentからインポート)
一時的な移行フラグも用意されている:
export default defineConfig({
legacy: {
collectionsBackwardsCompat: true,
},
});
その他の廃止・変更
<ViewTransitions />→<ClientRouter />にリネームAstro.glob()→import.meta.glob()に置き換えemitESMImage()→emitImageMetadata()getImage()がサーバー専用に(クライアント側で呼ぶとエラー)- CJS設定ファイル(
.cjs,.cts)非対応 i18n.routing.redirectToDefaultLocaleのデフォルトがfalseに- スクリプトとスタイルのレンダリング順序がコード定義順に変更
- 画像サービスがデフォルトでクロップ&アップスケール禁止に
このブログの移行で必要な作業
現在のプロジェクト構成を見て、Astro 6に移行する場合に必要な作業を整理した。
影響度: 大
コンテンツコレクションの移行が最も大きい。現在src/content/config.tsでレガシー形式を使っている。
// 現在の定義(Astro 5 レガシー形式)
import { defineCollection, z } from 'astro:content';
const articles = defineCollection({
type: 'content', // ← これが廃止
schema: z.object({ /* ... */ }),
});
移行後はこうなる:
// Astro 6 Content Layer API
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const articles = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/articles' }),
schema: z.object({ /* ... */ }),
});
加えて、article.slugを使っている箇所が大量にある。Astro 6ではslugがidに変わるため、プロジェクト全体で参照を書き換える必要がある。slug.split('/').pop()のパターンが20箇所以上ある。
entry.render()の変更も影響する。[slug].astroで使っているはずのrender()の呼び出し方が変わる。
影響度: 中
- Zodインポートの変更:
from 'astro:content'→from 'astro/zod'。src/content/config.tsで使用中 - Zod APIの変更: 現在のスキーマでは
z.string().email()のような影響を受けるAPIは使っていないが、Zodのバージョン差異でエッジケースが出る可能性はある - Shiki 4: コードブロックの表示が変わる可能性。ブログ記事にコードが多いので目視確認が必要
影響度: 小
- Node.js: 既にNode 22系を使用中。問題なし
- Vite 7: 直接Viteの設定をカスタマイズしている箇所が少なければ影響軽微
- Vitest:
^4.0.18で対応済み
移行の流れ
graph TD
A[Astro 6へのアップグレード] --> B[npx @astrojs/upgrade]
B --> C[コンテンツコレクション移行]
C --> D[config.ts → content.config.ts<br/>リネーム]
D --> E[loaderの追加<br/>type: content 削除]
E --> F[slug → id 参照の<br/>全箇所書き換え]
F --> G[render関数の<br/>呼び出し変更]
G --> H[Zodインポート変更<br/>astro:content → astro/zod]
H --> I[ビルド確認]
I --> J{エラーあり?}
J -->|Yes| K[個別修正]
K --> I
J -->|No| L[表示確認<br/>コードブロック・画像等]
L --> M[デプロイ]
急いで移行する必要はあるか
Astro 5系はまだメンテされており、^5.16.8で問題なく動いている。Astro 6.0はリリースされたばかり(4日前)なので、エコシステムの対応状況を見てから移行するのが安全。
実際に@astrojs/rssがZod 4の破壊的変更で壊れるissueが報告されているなど、周辺パッケージの対応がまだ追いついていない部分もある。1〜2ヶ月様子を見てパッチリリースが落ち着いてから移行するのが現実的。
Vite 8とRolldownの話
Astro 6はVite 7ベースだが、Astro 6リリースの3日後(3月13日)にVite 8.0がリリースされている。Vite 8の最大の変更はesbuildとRollupを廃してRust製バンドラーRolldownに一本化したことで、開発と本番のバンドル挙動差が解消された。実プロジェクトでのビルド速度改善も大きく、Linearが46秒→6秒(87%削減)、Beehiivが64%削減といった数字が報告されている。
Astro 6の開発サーバ再設計はViteのEnvironment APIを活用しているので、Vite 8のRolldown統合とは直接の依存関係はない。ただし、Astro 7でVite 8に移行する可能性は高く、そうなるとRolldownベースのビルドパイプラインとAstroの実験的Rustコンパイラが組み合わさることになる。ツールチェーン全体がどんどんRustに置き換わっている。
設定面では、Vite 8でesbuildオプションがoxcに、build.rollupOptionsがbuild.rolldownOptionsに変わるなどの破壊的変更がある。Astro側がこれを吸収してくれるはずだが、Viteの設定を直接カスタマイズしている場合は注意が必要。
Astro 6への移行を今すぐやるか、Vite 8対応のAstro 6.xパッチ(またはAstro 7)を待つかは悩ましいところだが、コンテンツコレクションの移行がどのみち必要なので、先にAstro 6に上げてからVite 8対応を待つのが順当だろう。
Fonts APIとCSPは地味に欲しかった機能。移行のハードルはコンテンツコレクションの書き換えが中心で、slug → idの全箇所修正が一番面倒そう。Rustコンパイラとキューレンダリングの実験的機能はv7に向けた布石で、パフォーマンス面が楽しみ。