Astroブログ作成:Astroで記事一覧ページを作る方法
はじめに
前回に続き、今回は、Astroを使った記事一覧ページを作成します。
Astroとは
Astroは、静的サイトジェネレーション(SSG)とJAMstackの機能を備えたフレームワークです。HTML、CSS、JavaScriptを記述することで、高速で読み込み速度の速いウェブサイトを作成することができます。
記事一覧ページの機能
今回は、以下の機能を実装することにします。
-
タグ情報に合わせて、サーバ関連、ネットワーク関連などの記事一覧と新着情報の記事一覧を表示する
-
記事が多い場合は、Pagining機能を使って次の記事一覧を表示する
-
記事のタイトル、概要、投稿日、ヒーロー画像などを表示する
-
記事へのリンクを表示する
記事一覧ページの作成
作成するファイルは、pages/blog/tags[tag]/[…page].astroになります。getStaticPaths関数でタグに関連する記事の一覧を作成します。なお新着情報は、タグとは関係ないため、新着順に記事一覧を作成しています。また、paginateを使って複数のページに分割して作成しています。今回は1つのページに9つの記事一覧が表示できるようにしました。
---
import BlogPList from '../../../layouts/BlogList.astro';
import type { GetStaticPathsOptions, Page } from 'astro';
import { getBlogs, type blog } from '../../../lib/utility';
export const getStaticPaths = async ({ paginate }: GetStaticPathsOptions) => {
const posts = await getBlogs(false);
var uniqueTags = [...new Set(posts.map((post: blog) => post.data.tags).flat())];
uniqueTags.push('news');
return uniqueTags.flatMap((tag) => {
const filteredPosts = tag === 'news' ? posts : posts.filter((post: blog) => post.data.tags.includes(tag));
var heroImages: string[] = [];
filteredPosts.map((post: blog) => {
heroImages.push(post.data.heroImage);
});
return paginate(filteredPosts, {
params: { tag: String(tag) },
props: { tag: tag },
pageSize: 9,
});
});
};
type Props = {
tag: string;
tagPosts: blog[];
page: Page;
};
const { page, tag } = Astro.props;
---
<BlogPList tag={tag} page={page} />
タグは、各記事のFrontMatterにタグを設定しています。複数の関連するタグを設定していますので、各タグごとに記事の一覧が作成されます。
---
title: 'EdgeRouterXをIPoEとPPPoEにしてみた。'
pubDate: 2020-08-10T22:40:00.000Z
heroImage: edgerouterx01.jpg
description: EdgerouterXでIPoEとPPPoEの両方を設定してみた。インターネット接続はIPoE(DS-Lite)、インターネットからホームサーバーへの接続はPPPoEです。
author: akibo.I
tags: [network, edgerouter, DS-Lite, PPPoE, router, IPv6]
---
記事一覧以外のコンポーネント
今回はAstro標準サンプルをもとに以下のコンポーネントを作成しました。
No | コンポーネント | 内容 | 備考 |
---|---|---|---|
1 | BaseHead | ベッダーのベースコンポーネント | ベッダー関連 |
2 | Header | ヘッダー | ベッダー関連 |
3 | HeaderLink | メニューの一覧、リンク | ベッダー関連 |
4 | Footer | フッター | フッター関連 |
5 | Card | 記事の要約 | 記事一覧、前後記事 |
6 | PrevNextNavi | 前後記事の誘導 | 他記事誘導ナビ |
7 | Pagination | 目次一覧を複数ページナビ | 他記事誘導ナビ |
8 | Tagnavi | タグ用ナビ | 他記事誘導ナビ |
9 | Toc | 目次ナビ | 他記事誘導ナビ |
10 | Theme | ダークモード切り替えナビ | 他記事誘導ナビ |
- 追加コンポーネント
- ダークモード対応
追加で作成したコンポーネントの中から、ダークモード対応コンポーネントを載せておきます。今回のブログは、Static Site Generation SSGモードで作成していますが、ダークモード対応するために、クライアントの操作で切り替えをできるようにします。
---
import { Icon } from 'astro-icon/components'
---
<button id="themeToggle" class="flex border-0">
<div class="flex">
<Icon
name="mdi:white-balance-sunny"
class="text-4xl dark:text-lg sm:text-4xl sm:dark:text-lg"
/>
<Icon name="mdi:weather-night" class="text-lg dark:text-4xl sm:text-lg sm:dark:text-4xl" />
</div>
</button>
<script is:inline>
const theme = (() => {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme')
}
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark'
}
return 'light'
})()
if (theme === 'light') {
document.documentElement.classList.remove('dark')
} else {
document.documentElement.classList.add('dark')
}
window.localStorage.setItem('theme', theme)
const handleToggleClick = () => {
const element = document.documentElement
element.classList.toggle('dark')
const isDark = element.classList.contains('dark')
localStorage.setItem('theme', isDark ? 'dark' : 'light')
}
document.getElementById('themeToggle').addEventListener('click', handleToggleClick)
</script>
共通の関数
今回いくつか共通的な処理があったので、まとめてutility.tsを作成して利用しています。ヒーロー画像は、OGPでも使えるように外部からのリンクを想定してpublicに配置しています。最後にその関数を載せておきます。
export async function getHeroImage(img: string) {
let imagePath = `/public/images/${img}`;
const images = import.meta.glob<{ default: ImageMetadata }>('/public/images/*.{jpeg,jpg,png,gif}');
if (!images[imagePath]) {
imagePath = `/public/images/${DEFAULT_IMAGE}`;
}
return images[imagePath]();
}
最後に
Astroに初めて挑戦した感想は、なんといっても簡単、すぐに動くものができる。インストールしてすぐにnpm run devで実行できるところが素晴らしいと思いました。あとは、インストールされたファイル、フォルダ構成をカスタマイズ、追加することでイメージ通りに作ることができました。nuxtやGatsby.jsの経験あればハードルは高くないと思います。またドキュメントも充実していたので助かりました。
また今回初めて、tailwindcssやrehype-pretty-codeを使って、node.jsの拡張性に驚きを覚えました。それに触発されて、ニッチだけど誰かに役に立つようなものが作れないか試行錯誤しています。近いうちに公開できればと思います。
Astroを使ってブログを作ってみたい方は、ぜひこの記事を参考にしてください。