前提
とある知り合いからの依頼でAstroを使い、CMS機能を含む静的サイトを作っている中で、投稿をTwitterのように縦に並べて表示したいという希望があった。
元々[...slug].astro内で各記事ごとにmarkdownファイルをHTML形式でレンダリングする部分は既にテンプレート内で実装されていたため、その内容を参考にタイムラインページを実装した際、勉強になった部分をこの記事では説明していく。
※この記事では、Astroについての説明や環境構築などには触れません。
Astroについての説明が気になる方は、下記の公式ドキュメントをご参照ください。
https://docs.astro.build/ja/getting-started/
環境
OS: MacOS Sequoia
node.js: v18.18.0
パッケージ管理ツール: yarn
Astro: 4.16.12
TypeScript: 5.6.3
結論
今回実装したソースコードは下記の通りである。なお、CSSや一部関係のないソースコードは割愛している。
---
import { getCollection } from "astro:content";
import FormattedDate from "../../components/FormattedDate.astro";
const rawPosts = await getCollection("blog");
const posts = await Promise.all(
rawPosts.map(async (post) => {
const { Content } = await post.render();
return { ...post, Content };
})
);
posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
---
<section>
<ul>
{posts.map((post) => (
<li>
<a href={`/blog/${post.slug}/`}>
<h4 class="title">{post.data.title}</h4>
<p class="date">
<FormattedDate date={post.data.pubDate} />
</p>
</a>
<post.Content />
</li>
))}
</ul>
</section>
解説
getCollection
冒頭でrawPostsに対して行なっているgetCollectionという関数は、astroプロジェクト内で使用できる、あるディレクトリ配下のファイルを全て取得するという関数である。
この関数を使用すると、src/content
配下のmarkdownファイルやMDXファイルなどを取得することができる。
今回は、src/conrent/blog
配下のmarkdownファイルを取得したかったため、getCollection("blog")
と指定している。
post.render
render関数とは、Astroプロジェクト内で使用できる、MarkdownおよびMDXファイルをHTMLにレンダリングできる関数である。
この関数を使うことで、レンダリングされた記事の内容を取得することができる。
その後、post
オブジェクトにContent
を追加し、最終的にpostsにレンダリングされた内容を含む配列が格納される。
post.sort
pubDateとは、markdownファイル内で定義している日時である。その日時の値を元に、投稿順が新着順になるようソートしている。
所感
今までReactやWordPressなどで同様の機能を実装したことはあったが、Astroはmarkdownファイルを配置すれば内部で使用できる関数を使用することでCMS機能がついたサイトを実装することができた。
また、AstroはNetlifyなどのホスティングサービスとも相性が良いため、ビルドやリリース管理も非常に簡単に行うことができ使用感はとても良い。