Astroのバージョンを4系から5系にアップグレードした際のメモ
当サイトで使用しているAstro.jsのバージョンを4系から5系にアップグレードしました。
メジャーレベルの変更ということもあり少しつまづく点もありましたが、公式ガイドを参考になんとか完了することができました。苦労した点を中心にメモを残しておきます。
依存関係のエラー解消
公式ガイドに沿ってnpx @astrojs/upgradeのコマンドを実行すると早速エラーが発生しました。
error Dependencies failed to install, please run the following command manually: npm i @astrojs/mdx@4.2.1 @astrojs/rss@4.0.11 @astrojs/sitemap@3.3.0 @astrojs/vercel@8.1.3 @astrojs/vue@5.0.7 astro@5.5.4 @astrojs/partytown@2.1.4どうやらAstro v4からv5へのアップグレード中に依存関係のインストールが失敗したようです。一部のパッケージについては手動でインストールせよということなので、その通りにコマンド実行します。
すると今後は次のようなエラーが発生しました。
npm ERR! Found: @astrojs/mdx@3.1.9npm ERR! node_modules/@astrojs/mdxnpm ERR! @astrojs/mdx@"4.2.1" from the root project(省略)npm ERR! Conflicting peer dependency: astro@5.5.4npm ERR! node_modules/astronpm ERR! peer astro@"^5.0.0" from @astrojs/mdx@4.2.1npm ERR! node_modules/@astrojs/mdx@astrojs/mdx@4.2.1をインストールしようとしていますが、@astrojs/mdx@4.2.1のインストールにはAstro v5以上が必要なようです。現在のプロジェクトはまだv4を使用しているため、この依存関係の要件が満たされていないようです。
package.jsonを手動で編集して、まずAstroのバージョンを5系に上げてから、エラーが発生していたインテグレーションを個別にアップデートすることでうまくいきました。
コンテンツコレクションからコンテンツレイヤーへ
今回のアップグレードのメインイベントです。
これまでは静的なコンテンツの管理に「コンテンツコレクション」を用いてきましてが、Astro v5からは「コンテンツレイヤー」をなるものが出現しました。コンテンツレイヤーではGitリポジトリのマークダウンファイル以外にも、CMSや外部のAPIのデータを集約して管理を行うことができます。
さっそく公式ガイドにある コレクションを更新するための手順に沿って作業を行います。
これまでのsrc/content/config.tsをsrc/content.config.tsに移動しリネームします。そしてコレクションの定義を下記のようにtypeオプションから、loaderオプションに変更しました。
import { z, defineCollection } from "astro:content";import { glob } from "astro/loaders";
const newsCollection = defineCollection({ type: 'content', loader: glob({ pattern: "**/*.md", base: "./src/data/news" }), schema: z.object({ title: z.string(), pubDate: dateStringSchema, description: z.string(), tag: z.object({ name: z.string(), label: z.string(), }), }),});当サイトのNewsのファイルはsrc/content/news/のディレクトリに置いていましたが、コンテンツレイヤーでは任意の場所にファイルを設置できるためsrc/data/news/へと記事を移動しました。
slugからidへの参照変更
v4まではslugというフィールド名でコンテンツを参照していましたが、v5ではidというフィールド名に変更されています。記事詳細ページテンプレートの該当箇所を変更します。
export async function getStaticPaths() { const newsEntries = await getCollection("news"); return newsEntries.map((newsEntry) => ({ params: { slug: newsEntry.slug }, params: { slug: newsEntry.id }, props: { newsEntry }, }));}他にもRSSフィードを出力しているrss.xml.jsやトップページのテンプレートにおいてもslugフィールドを参照していたのでidに変更しました。slugのままだとアンカーリンク等が正しく動作しない可能性があるため注意が必要です。
render関数への変更
v4までのrenderメソッドを、v5ではrender関数へと置き換えます。astro:contentからrender()関数を直接インポートして使用します。
import { getCollection } from "astro:content";import { getCollection, render } from "astro:content";
const { newsEntry } = Astro.props;const { Content } = await newsEntry.render();const { Content } = await render(newsEntry);以上でコンテンツレイヤーへの変更が完了しました。当サイトではNewsの他にBlogの記事もコンテンツコレクションで管理していたため、こちらも上記の流れに沿ってコンテンツレイヤーへと変更しました。
レンダリングモードの調整
v5からはレンダリングモードのhybridが削除されました。
当サイトは基本的にはSSGで運用していますが、制作実績詳細ページのプレビュー画面ではSSRを使用しています。そのためastro.config.mjsのoutputを変更します。
import { defineConfig } from "astro/config";
export default defineConfig({ output: "hybrid",});デフォルトオプションのstaticでこれまでのhybridと同じような動きをするようです。SSRとして設定したいページのフロントマター内で、export const prerender = false;と宣言することで、サーバーサイドレンダリングを有効化することができます(これまで通り)。
SSRアダプター
SSRには@astrojs/vercel/serverlessというvercelのパッケージを使用していましたがこれを次のように変更する必要があります。
import vercel from "@astrojs/vercel/serverless";import vercel from "@astrojs/vercel";v5では@astrojs/vercelを直接インポートし、アダプターのオプションでデプロイタイプを設定するようです。
従来のような特定のデプロイ先を指定したサブパスからのインポートは非推奨となり、代わりにルートパッケージから直接インポートする方法が推奨されています。
ViewTransitionsコンポーネント名を変更
v4まではView Transitions APIを使用するために<ViewTransitions />コンポーネントを使用していましが、v5ではコンポーネントの名前を<ClientRouter />に変更する必要があるようです。
import { ViewTransitions } from 'astro:transitions';import { ClientRouter } from 'astro:transitions';
<html> <head> ... <ViewTransitions /> <ClientRouter /> </head></html>名前が変わっただけで機能に変更はなく、コンポーネントの役割をより明確にするためのようです。
あとがき
アップグレード時点で公式ガイドに日本語版がありませんでしたが、Googleの翻訳機能等を使用することでなんとか全体を通して理解することができました。
そもそもすでに構築が完了し運用フェーズに入っているWebサイトでは、わざわざAstroをアップグレードしなくても良いのかなとも思っています(不具合がでていたら別ですが)。
今後新たに追加される機能も使ってみたいなというモチベーションがあったので今回は重い腰を上げてアップデートに踏み切りました。どなたかの参考になれば幸いです。
