このサイトで使用しているAstroフレームワークを、バージョン5.12から6.0にアップグレードしました。その際、いくつか手動で修正が必要な箇所があったため、作業内容を備忘録として記録しました。

Astro 6の主な新機能

Astro 6では以下の機能が追加されました。

  • 再設計されたastro dev — Viteの環境APIを活用することで、本番環境と同じランタイムで開発できます
  • 組み込みフォントAPI — 面倒な作業を自動で処理する組み込みフォントAPIが追加され、Google FontsやFontsourceなどのフォントを設定ファイルで管理できます
  • ライブコンテンツコレクション — ビルドなしでCMSやデータベースの更新をリアルタイムに反映できます
  • コンテンツセキュリティポリシー — スクリプトとスタイルの自動ハッシュ機能が統合されました

詳しくは公式のアップデート情報をご確認ください。

アップグレード手順

公式が提供している以下のコマンドを実行するだけで、Astro本体と公式インテグレーション(@astrojs/*)をまとめて更新できます。

npx @astrojs/upgrade

修正が必要だった箇所

コマンド一発でアップグレードはできますが、Astro 6ではいくつか破壊的変更があり、環境によっては手動での修正が必要になることがあります。以下、自分の環境で生じた修正事項をまとめました。

Node.js 22以上が必須

Astro 6はNode.js 22.12.0以上が必須ですが、Vercelのデプロイ環境がNode.js 20のままだったためビルドエラーになりました。

package.jsonenginesフィールドを追加してバージョンを明示し、VercelのダッシュボードのProject SettingsNode.js Version22.xに変更することで解決しました。

{
  "engines": {
    "node": ">=22.12.0"
  }
}

@astrojs/vercel のインポートパス変更

@astrojs/vercelがv10になり、インポートパスが変わりました。

// Before
import vercel from '@astrojs/vercel/static';

// After
import vercel from '@astrojs/vercel';

コンテンツコレクションの設定ファイルが移動

Astro 6ではレガシーなコンテンツコレクションAPIが廃止され、新しいContent Layer APIへの移行が必要になりました。

変更点は主に3つです。

1. 設定ファイルの移動

src/content/config.tssrc/content.config.ts(プロジェクトルート直下)

2. loaderの追加とzのインポート元変更

各コレクションにloader: glob(...)が必須になりました。またzのインポート元がastro:contentからastro/zodに変わりました。

// Before (src/content/config.ts)
import { defineCollection, reference, z } from 'astro:content';

const blog = defineCollection({
  type: 'content',
  schema: z.object({ ... }),
});
// After (src/content.config.ts)
import { defineCollection, reference } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';

const blog = defineCollection({
  loader: glob({ pattern: '**/[^_]*.{md,mdx}', base: './src/content/blog' }),
  schema: z.object({ ... }),
});

3. slugidrender()の書き方変更

エントリーの識別子がpost.slugからpost.idに変わりました。また記事コンテンツのレンダリング方法も変わりました。

// Before
const { Content, headings } = await post.render();

// After
import { render } from 'astro:content';
const { Content, headings } = await render(post);

リモート画像のリダイレクト非対応

このサイトのメインビジュアルは picsum.photos のランダム画像を読み込んで、Astroの<Picture>コンポーネントで最適化するという処理を行なっています。Astro 6(Vite 7)ではリモート画像取得時にHTTPリダイレクト(302)をエラーとして扱うようになったため、500エラーが発生しました。

fetchでリダイレクトを辿って最終的なURLを取得してから<Picture>コンポーネントに渡すことで解決しました。

---
const picsumUrl = `https://picsum.photos/1600/1200?date=${new Date()}`;
const res = await fetch(picsumUrl, { redirect: 'follow' });
const resolvedUrl = res.url;
---
<Picture src={resolvedUrl} ... />

あわせて、リダイレクト先のドメインもastro.config.mjsimage.domainsに追加しました。

image: {
  domains: ["picsum.photos", "fastly.picsum.photos"],
},

まとめ

npx @astrojs/upgradeでほとんどの作業は完了しますが、コンテンツコレクションを使用している場合は、いくつか追加で変更を行う必要があります。 とはいえ、Claude CodeなどのAIエージェントを使っている場合は、アップグレードに付随したエラーの洗い出しと修正もほぼ自動で行なってくれるので、かなり楽だと思います。

よきAstroライフを!