背景

Astro 4 + MDX + Tailwind CSS で構築していたウェブサイトで、pnpm の overrides により astro 5.x が強制的にインストールされる状態になっていました。@astrojs/mdx@2.x(Astro 4 用)と astro 5.x の間で互換性がなく、ビルドが失敗していました。

Package subpath './jsx/renderer.js' is not defined by "exports" in astro/package.json

Astro 4 に戻すよりも、Astro 5 へアップグレードする方が合理的と判断し、移行を実施しました。

変更点

1. パッケージの更新

// Before
"@astrojs/mdx": "^2.0.0",
"astro": "^4.0.3"

// After
"@astrojs/mdx": "^4.0.0",
"astro": "^5.0.0"

@astrojs/tailwindtailwindcss はそのままです。

2. Content Collections の type 指定を削除

Astro 5 では defineCollectiontype: "content" が不要になりました。

// Before
const news = defineCollection({
  type: "content",
  schema,
});

// After
const news = defineCollection({
  schema,
});

3. entry.slug から entry.id への変更

Astro 5 では Content Collections の slug プロパティが廃止され、id に統一されました。

ただし、id にはファイル拡張子(.md, .mdx)が含まれるため、URLとして使う場合は拡張子を除去する必要があります。

// Before
params: { slug: entry.slug }
link={import.meta.env.BASE_URL + "datasets/" + dataset.slug}

// After
params: { slug: entry.id.replace(/\.\w+$/, '') }
link={import.meta.env.BASE_URL + "datasets/" + dataset.id.replace(/\.\w+$/, '')}

フィルタや並び替えで定数と比較する箇所も同様に修正が必要でした。

// Before
.filter((service) => datasetList.includes(service.slug))

// After
.filter((service) => datasetList.includes(service.id.replace(/\.\w+$/, '')))

4. entry.render() から render(entry) への変更

Astro 5 では renderastro:content からインポートして使う形式に変わりました。

// Before
import { getCollection } from "astro:content";
const { Content } = await entry.render();

// After
import { getCollection, render } from "astro:content";
const { Content } = await render(entry);

5. entry.body の廃止

Astro 5 では entry.body(マークダウンの生テキスト)に直接アクセスできなくなりました。代わりに entry.data.description などフロントマターのフィールドを使います。

// Before
<p>{item.body}</p>

// After
<p>{item.data.description}</p>

対象ファイル

変更が必要だったファイルは以下の通りです。

  • package.json
  • src/content/config.ts
  • src/pages/datasets/[...slug].astro
  • src/pages/datasets/index.astro(変更なし)
  • src/pages/news/[...slug].astro
  • src/pages/news/index.astro
  • src/pages/services/[...slug].astro
  • src/pages/services/index.astro(変更なし)
  • src/components/NewsSection.astro
  • src/components/DatasetSection.astro
  • src/components/ServiceSection.astro
  • src/components/Footer.astro
  • src/components/SidePanel.astro
  • src/layouts/ListLayout.astro

所感

変更自体は機械的で、ほぼ slugid(拡張子除去付き)の置換と render() の呼び出し方の変更でした。Content Collections を使っているプロジェクトであれば、半日もかからずに移行できると思います。