Astro v6 betaへのアップグレード作業まとめ

はじめに

Astro v6 betaが​リリースされたので、​この​ブログを​アップグレードしました。​その​際に​行った​作業を​まとめます。

アップグレードコマンドの​実行

1
pnpm dlx @astrojs/upgrade beta

これに​より​以下の​パッケージが​更新されました。

パッケージ旧バージョン新バージョン
astro5.12.96.0.0-beta.4
@astrojs/mdx4.3.35.0.0-beta.2
@astrojs/check0.9.40.9.7-beta.1
@astrojs/rss4.0.124.0.15-beta.2
@astrojs/sitemap3.4.23.6.1-beta.2

Node.js 22が​必須に

Astro 6は​Node.js 22.12.0以上が​必須に​なりました。​この​ブログでは​パッケージマネージャーに​pnpmを​使っているので、package.jsondevEnginesを​追加して​pnpmに​管理させる​ことができます。

123456789
{
  "devEngines": {
    "runtime": {
      "name": "node",
      "version": ">=24",
      "onFail": "download"
    }
  }
}

flake.nixと​package.jsonの​両方を​更新するのは​面倒なので、​どうにかしたい​ところです。。

実験的フラグの​削除

astro.config.mjsからexperimental.liveContentCollectionsを​削除しました。​Astro 6では​安定版に​なった​ため、​廃止された​フラグです。

123
- experimental: {
-   liveContentCollections: true,
- },

【v6関係ない​】Content Collections設定ファイルの​移行

個人的に​衝撃を​うけましたが、​v6の​migrationとは​関係​ありません。
これっていつ​変更されたんでしょうか?

ファイル移動

1
src/content/config.ts → src/content.config.ts

loaderの​明示的な​定義が​必須に

Before:

12345678910111213141516
import { defineCollection, z } from "astro:content";

const blogCollection = defineCollection({
  schema: z.object({
    title: z.string(),
    pubDate: z.date().transform((v) => new Date(v)),
    // ...
  }),
});

const dailyCollection = defineCollection({
  type: "content",  // これだけで​OKだった
  schema: z.object({
    pubDate: z.date().transform((v) => new Date(v)),
  }),
});

After:

12345678910111213141516171819
import { defineCollection } from "astro:content";
import { glob } from "astro/loaders";
import { z } from "zod";  // zodから​直接インポート

const blogCollection = defineCollection({
  loader: glob({ pattern: "**/*.mdx", base: "./src/content/blog" }),
  schema: z.object({
    title: z.string(),
    pubDate: z.coerce.date(),  // z.coerce.date()が​簡潔
    // ...
  }),
});

const dailyCollection = defineCollection({
  loader: glob({ pattern: "**/*.mdx", base: "./src/content/daily" }),
  schema: z.object({
    pubDate: z.coerce.date(),
  }),
});

変更ポイント

  1. zの​インポート元: astro:contentzodastro:contentからのzは​非推奨)
  2. loader必須: glob()関数で​明示的に​ファイルパターンと​ベースディレクトリを​指定
  3. z.coerce.date()推奨: z.date().transform()より​簡潔

zodパッケージの​追加

Astro 6ではzodを​直接インポートする​ため、​依存関係に​追加が​必要:

1
pnpm add -D zod

slugidへの​変更

コレクションエントリのslugプロパティが​廃止され、idに​変更されました。
​書き換えが​面倒だったので、​AIに​やらせました。

Before:

12345678
// getStaticPaths
return posts.map((post) => ({
  params: { slug: post.slug },
  props: posts.find((x) => x.slug === post.slug),
}));

// テンプレート内
<a href={`/blog/${post.slug}`}>

After:

12345678
// getStaticPaths
return posts.map((post) => ({
  params: { slug: post.id },
  props: posts.find((x) => x.id === post.id),
}));

// テンプレート内
<a href={`/blog/${post.id}`}>

この​ブログで​影響を​受けた​ファイル例:

render()メソッド → render()関数

コンテンツの​レンダリング方​法が​変更されました。

Before:

12
const post = Astro.props;
const { Content } = await post.render();

After:

1234
import { getCollection, render } from "astro:content";

const post = Astro.props;
const { Content } = await render(post);

注意点・課題

サードパーティパッケージの​互換性

astro-zenn-loaderastro-og-canvasなど、​まだ​Astro 6に​対応していない​パッケージが​あります。​peerDependency警告は​出ますが、​動作する​場合が​多いです。

おわりに

Astro 6への​アップグレードで​最も​影響が​大きいと​感じたのは​Content Collectionsの​変更です。loaderの​明示的定義、slugidrender()の​変更など、​コンテンツ周りの​破壊的変更が​多いため、​ブログサイトでは​修正箇所が​多くなりがちです。

また、​Node.js 22が​必須に​なった​ため、​CI/CDパイプラインや​デプロイ環境の​Node.jsバージョンも​確認が​必要です。

参考リンク