Astro 6 へのバージョンアップに備えて、開発ブログと wiki の記事の読み込み方を新形式へ移した

背景

Astro 6 へのバージョンアップに向けた下ごしらえの2つ目です。1つ目では、Cloudflare の環境変数などを取り出す書き方を、共通関数1つに集めました。

今回は、開発ブログと wiki の Markdown 記事の読み込み方です。

何が変わるのか

Astro では、Markdown で書いた記事の集まりを「コンテンツコレクション」と呼びます。Astro 5 には古い形式と新しい形式の2つがあり、このサイトは古い形式を使っていました。Astro 6 では古い形式が廃止され、古い設定ファイルがあるだけでエラーになります。

項目 古い形式 新しい形式
設定ファイル src/content/config.ts src/content.config.ts
記事の読み込み方 type: 'content'(フォルダを自動で読む) loader: glob(...)(読むフォルダを指定する)
記事の名前(URLになる部分) entry.slug entry.id
本文を表示用に変える entry.render() render(entry)

Astro 5 は新しい形式にすでに対応しているため、バージョンアップの前に、今のバージョンのまま移せます。

対処

1. 設定ファイルを新形式で作り直した

開発ブログ(src/content/devblog/)と wiki(src/content/wiki/)を、glob ローダーで読むように設定しました。記事のURLはファイル名から作られます。新しい形式でも同じ規則でURLが作られるため、記事のURLは変わりません。

調べる途中で、古い設定には少し食い違いがあることにも気づきました。項目の決まり(スキーマ)は、中身が空の別のコレクションに付いていて、実際の開発ブログ記事には付いていませんでした。今回は「ふるまいを変えない」ことを優先し、この状態をそのまま新形式に移しています。

2. 呼び出し側の書き換えを最小にする共通関数を挟んだ

entry.slug と entry.render() は、サイト中の多くの場所で使われていました。中には、データベースから読んだ値の slug と同じ名前で並んでいる場所もあり、1つずつ書き換えると取り違える恐れがありました。

そこで、新しい形式で読んだ記事に slug と render() を付け足して返す共通関数を作りました。

// 新しい形式で読んだ記事を、今までと同じ形に整えて返す
export async function getContentEntries(name, filter) {
  const entries = await getCollection(name, filter);
  return entries.map((entry) => ({
    ...entry,
    slug: entry.id,                  // 古い形式の slug は、新しい形式の id
    render: () => render(entry),     // 本文の表示用変換
  }));
}

呼び出し側は、getCollection を getContentEntries に置き換えただけです。

確かめたこと

移す前と後で、ビルド成果物(ビルドで出来上がったファイル一式)を本番と同じ実行環境(workerd)で動かし、次のページの出力を保存して見比べました。

ページ 結果
開発ブログの一覧・記事ページ 完全に同じ
wiki の一覧・用語ページ 完全に同じ
年別アーカイブ・RSS 完全に同じ
サイトマップ 載っている記事は同じ。並び順だけが変わった

サイトマップの並び順は、検索エンジンの扱いに影響しません。

学んだこと

参考