Astro6に上げたら記事が空になった
Astro6アップデート後に出たcontent collectionsエラーと、実際に直したコードのメモ。
Astro6に上げたあと、ビルドでこんなエラーが出ました。
The collection "posts" does not exist or is empty.
Please check your content config file for errors.
原因はcontent collectionsの扱いが変わっていたことでした。
何が変わっていたか
- 旧来の
type: 'content'だけの定義では足りず、loaderが必要だった post.slug前提のコードがv6ではそのまま使えなかった
変更したコード
まずは src/content.config.ts。
ここを glob() を使う形に変更しました。
// before
import { defineCollection, z } from 'astro:content';
const posts = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
description: z.string(),
ogImage: z.string().optional(),
publishedAt: z.coerce.date(),
draft: z.boolean().optional().default(false),
}),
});
export const collections = {
posts,
};
// after
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const posts = defineCollection({
loader: glob({
pattern: '**/[^_]*.{md,mdx}',
base: './src/content/posts',
}),
schema: z.object({
title: z.string(),
description: z.string(),
ogImage: z.string().optional(),
publishedAt: z.coerce.date(),
draft: z.boolean().optional().default(false),
}),
});
これでpostsコレクションの読み込み元をAstroにちゃんと伝えられるようになりました。
z のimportもastro/zodに変更しています。
次にpost.slugを使っていた部分。
今回はpost.idから URL用の文字列を作るようにしました。
export const getPostSlug = (post: PostEntry): string => {
return post.id.replace(/\.(md|mdx)$/, '');
};
これを使って、詳細ページや関連記事のリンクを組み立てるように変更。
return posts.map((post) => ({
params: { slug: getPostSlug(post) },
props: {
post,
relatedPosts: pickRandomPosts(posts, getPostSlug(post), 3),
},
}));
一覧側のリンクも同じです。
<a href={`/posts/${getPostSlug(post)}/`}></a>
直したあと
修正後はastro checkもastro buildも通るようになりました。
メジャーアップデートって、やっぱり何かしらこういった変更が入ることがありますね。
依存更新自体はすぐ終わっても、こういうところで少しハマります。
同じエラーに当たったら、
content.config.tsがv6の形になっているかslug前提のコードが残っていないか
このあたりを見ると早そうです。 あと、公式ドキュメントはちゃんと読んだほうが早いっすね。
以上、おわり。