この記事は ryota2357 Advent Calendar 2024 の 8 日目の記事です。
5 日ほど前の 12/3 に Astro.js v5 がリリースされた。 この v5 の一番の注目点は Content Layer であろう。
このサイト現在は Astro.js で構築されている。
今回 v5 がリリースされたので Content Collection で管理・生成されていた各記事を Content Layger に移行した。
また、ViewTransitions
コンポーネントの名前変更と、TypeScript 型ファイルの移動の対応も行った。
これら v4 から v5 への移行で行ったことを書いていく。
コミット (PR)
変更は ryota2357/ryota2357.com#309 にて行われた。 Renovate のバージョンアップ PR にコミットを繋げている。
Content Layger
Experimental の時に Content Layer を使用した日本語記事があったのでこれを参考に導入した。コミットは f6362ca。
Astro4.14 Content Layer API - 趣味のNote
記事(markdown)の移動
Content Collection の時は Content を置けるのが src/content 以下に制限されていたが、Content Layger ではそれがなくなった。 これまでブログ記事は src/content/blog においていたのを content/blog に移動した。
なお、Content Layger の設定は Content Collection の時と同様、src/content/config.ts で行うので、これは動かしてはいけない。
また、僕は Content Collection で記事以外に src/Content/works/ 以下で yaml ファイルを管理している。 今回これらの Content Layger への移行は行わなかった。 このことから、Astro.js v5 では Content Collection と Content Layger の共存可能であることがわかった。
src/content/config.ts の修正
記事を Content Layger に移行するため該当部分を修正する。 Content Layger に移行せず、Content Collection を引き続き使用するものに関しては修正する必要はない。
import { defineCollection, z } from "astro:content";
+import { glob } from "astro/loaders";
const blogCollection = defineCollection({
- type: "content",
+ loader: glob({ pattern: "**/*.md", base: "./content/blog" }),
schema: z.object({
title: z.string(),
postdate: z.coerce.date(),
update: z.coerce.date(),
tags: z.array(z.string()),
draft: z.boolean().optional().default(false),
}),
});
CollectionEntry<C>["slug"]
を CollectionEntry<C>["id"]
にする
Content Layger にすると、getCollection
で取得できていたオブジェクトから slug
フィールドがなくなる。
おそらく型エラーがでているはず (もしくは astro check とかででるはず) なので、それらを id
フィールドに書き換える。
src/pages/blog/[year]/[slug].astro
<ul class="mx-0 my-4 grid grid-flow-col justify-between gap-3">
<li>
{prevPost && (
- <a href={path.join("/blog", prevPost.slug, "/")} rel="prev">
+ <a href={path.join("/blog", prevPost.id, "/")} rel="prev">
← {prevPost.data.title}
</a>
)}
</li>
<li>
{nextPost && (
- <a href={path.join("/blog", nextPost.slug, "/")} rel="next">
+ <a href={path.join("/blog", nextPost.id, "/")} rel="next">
{nextPost.data.title} →
</a>
)}
先ほどあげた参考記事では [...slug].astro のファイル名を [...id].astro に変えていたが、僕は変えず、[...slug].astro のままにした。
フィールド名は確かに id
に変わったが、slug
の方が具体的なので、コード・ファイルの意味がわかりやすいと思ったからだ。
render の変更
getCollection
で取得できたオブジェクトから render
フィールドがなくなった。
astro:content
から render
関数を import してそれを利用するようだ。
src/pages/blog/[year]/[slug].astro
import path from "node:path";
import { Image } from "astro:assets";
+import { render } from "astro:content";
import { util, allBlogCollection } from "@/content";
...省略
type Props = InferGetStaticPropsType<typeof getStaticPaths>;
const { post, prevPost, nextPost } = Astro.props;
-const { Content } = await post.render();
+const { Content } = await render(post);
const formatTime = (time: Date) => dayjs(time).format("YYYY/MM/DD (HH:mm)");
---
ViewTransitions コンポーネントの名前変更
v5 での Breaking Changes のうちの 1 つである。 コミットは 4b9d2bf。
Upgrade ガイド (Renamed: <ViewTransitions />
component) に書いてある通りだが、ただ名前を変えればいいだけである。
import "destyle.css";
-import { ViewTransitions } from "astro:transitions";
+import { ClientRouter } from "astro:transitions";
import Footer from "@/components/Footer.astro";
import HeadSEO from "@/components/HeadSEO.astro";
}
}
</style>
- <ViewTransitions />
+ <ClientRouter />
</head>
<body>
TypeScript 型ファイルの移動
src/env.d.ts から .astro/types.d.ts に移動された。コミットは 0f6a078。
これも Upgrade ガイド (Changed: TypeScript configuration) の通りに修正すれば良い。
最後に
Astro.js は v3 の頃に Gatsby.js から移行したので、今回でメジャーバージョンアップは 2 回目だった。
v3 -> v4 は get
を GET
に変えるくらいの小さなものだったと記憶しているが、今回 v4 -> v5 は Content Layger への移行もありコードをいくつか書き換えた。
しかしその作業は参考記事の存在もありスムーズに行えた。