Astro 5.0の新機能(Content Layer API / Server Island)
この記事は、Astro 5.0の新機能「Content Layer API」と「Server Island」の解説です
ブログ記事
アップグレードガイド雑感
Astroは、コンセプトのCoreにNo JavaScript / Less JavaScript
で、
ビルド後にJavaScriptが少なくなること=パフォーマンスが良くなる、という設計思想がベースにあります
静的な画面であることを基本とし、JavaScriptを使ったインタラクティブなUIが必要なところはAstro Island、サーバーからのデータ取得が必要なコンポーネントはServer Island
というふうに、JavaScriptを減らす方針と考えています
Content Collection APIから、Content Layer APIへ
Content Collectionは、ローカルファイル(mdxやjson)を管理する方法として登場しました
Astro 5.0以降は、ローカルファイルに限らず、リモートのAPIから取得したデータも、Contents Collectionとして扱えるようになりました
実装方法
1. Content Collectionの定義
src/content.config.jsか、src/content/config.tsにContent Collectionを定義します
loaderにfetchする関数を書き、schemaにzodを使ってContent Collectionのデータ型を定義します
// src/content.config.ts
import { defineCollection, z } from 'astro:content';
const news = defineCollection({
loader: () => fetch('https://api.example.com/news').then(res => res.json()),
})
schema: z.object({
id: z.string(),
title: z.string(),
slug: z.string(),
publishDateTime: z.string(),
})
;
export const collections = { news }
2. 記事一覧で、Contents Collectionを表示
---
const newsList = await getCollection("news");
---
{
newsList.map((item) => (
<li>
<a href={`/news/article/${item.data.path}`}>
<p>{item.data.publishDate}</p>
<p>{item.data.title}</p>
</div>
</a>
</li>
))
}
ここのnewsListの型は、CollectionEntry型を使って、type NewsList = CollectionEntry<"newsCollection">[]
となります
Server Island
Astroの主要機能である、アイランドアーキテクチャのコンセプトをサーバーまで拡張し、
ログインやショッピングカート部分をアイランドアーキテクチャを使って表示できるようになりました
つまり、
「①完全に静的であり変化しないコンテンツ」「②データベースにより変化するコンテンツ」「③個々のユーザーに合わせてパーソナライズされたコンテンツ(ログイン状態が必須)」が混ざる場合、
③に合わせてCDNキャッシュできなかったものが、キャッシュできるようになります
実装例
Server Islandとしてレンダリングしたいコンポーネントにserver:defer
を追記、
内包するフォールバック用コンポーネントにslot="fallback"
を記述します
import Avatar from '../components/Avatar.astro';
import GenericAvatar from '../components/GenericAvatar.astro';
---
<Avatar server:defer>
<GenericAvatar slot="fallback" /> ← fallbackコンテンツ
</Avatar>
これに伴って、output: hybrid
は廃止され、
output: 'static'
と、全てSSRとするoutput: 'server'
の2つになりました
Discussion