日々進化するウェブ開発の世界では、新しいツールやフレームワークが次々と登場しています。
そのなかでも一際注目を集めているのが、Astroと呼ばれる静的サイトビルダーです。
そこでこの記事では、Astroを使用してウェブサイトを構築する方法について詳しく解説します。
Astro.jsは、効率性とパフォーマンスを重視した現代的なウェブ開発フレームワークです。
この記事では、Astro.jsの基本から、初めてのプロジェクト作成、さらに応用技術に至るまでを解説します。
Astroとは?
Astroとは、高速なウェブサイトを構築するための静的サイトビルダーです。
AstroはMPA(Multi-Page Application)を採用しており、ビルド時に不必要なJavaScriptを削除して生成します。
Astroを採用する理由としては、主に以下の3つが挙げられます。
- ページロード速度の向上
- SEOの最適化
- 開発体験の改善
Astro.jsは、静的サイト生成に特化したモダンなフレームワークです。
高速なパフォーマンスと効率的なウェブ開発を実現するために設計されており、ReactやVueなどの人気のあるフレームワークとの互換性があります。
その特徴は、サイトの読み込み速度を高めるために、JavaScriptの使用を最小限に抑えることにあります。
初めてのAstro.jsプロジェクト
Astro.jsを使ったプロジェクトの開始はシンプルです。
Node.js環境をセットアップした後、以下のコマンドを実行して新しいプロジェクトを作成します。
npm init astro
このコマンドは、基本的なファイル構造と必要な依存関係をセットアップし、プロジェクトのスタート地点を提供します。
Astro.jsの基本的な構造
Astro.jsプロジェクトの構造は直感的で理解しやすいです。
主要なファイルとディレクトリには、src/
(ソースコード)、public/
(静的アセット)、そしてastro.config.mjs
(設定ファイル)が含まれます。
src/pages/
ディレクトリ内に配置された.astro
ファイルは、ウェブサイトの各ページを定義し、MarkdownやJSXといった異なるテンプレート言語をサポートします。
Astroの特徴:Astro Islands
Astroの特徴の一つに、Astro Islandsという概念があります。
Astro Islandsを一言で表すと、アイランドアーキテクチャを採用したウェブアーキテクチャ。
つまり、ページ内でサーバ側でレンダリングされる静的な部分とインタラクティブな部分をそれぞれ独立して表示させる手法がAstro Islandsです。
独立したコンポーネントごとにハイドレーションを行い、不必要なJavaScriptを削減してパフォーマンスを向上させます。
Astroでは、それらの独立したコンポーネントごとに使用したいUIフレームワークを選択することができるので、フレームワークに依存することなく実装を行えるという利点があります。
状態管理:Nano Stores
ページ内外での状態共有で使用するのが、Nano Storesという軽量な状態管理ライブラリです。
Nano Storesはフレームワークに依存していないため、フレームワーク間での状態管理がしやすいというメリットがあります。
また、AstroではPartial Hydrationという、明示的にクライアントサイドのJSを定義する必要があるため、Wrapperの使用は不可です。
ReduxやContext Providerなどの使用を考えている方は注意しましょう。
Astro.jsでのウェブ開発
Astro.jsでのコンポーネント作成
Astro.jsでは、コンポーネントベースのアプローチを採用しています。
これにより、再利用可能なUIパーツを作成し、ウェブサイトの各部分を効率的に管理できます。
コンポーネントは.astro
ファイルで定義され、HTMLと同様の構文で書かれますが、JavaScriptや他のフレームワークのコードも組み込むことが可能です。
例えば、以下はシンプルなコンポーネントの例です。
<div>
<h1>{props.title}</h1>
<p>{props.content}</p>
</div>
このコンポーネントは、title
とcontent
というプロパティを受け取り、それらを表示します。
スタイリングとレイアウト
Astro.jsでは、CSSやSCSSなどのスタイリング手法を直接利用することができます。
また、コンポーネントごとにスコープされたスタイルを適用することも可能で、これによりグローバルなスタイルの衝突を避けられます。
レイアウトに関しては、Astro.jsはフレキシブルで、様々なレイアウトパターンをサポートしています。
たとえば、以下のようにCSS Gridを使用したレスポンシブレイアウトを簡単に実装できます。
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
APIとの連携
Astro.jsでは、外部APIからデータを取得し、それをウェブサイトに統合することが容易です。
fetch
APIを使用して、サーバーサイドでデータを取得し、それをコンポーネントで表示することができます。
例えば、以下のコードは外部APIからデータを取得し、それをリストとして表示する方法を示しています。
const response = await fetch('https://api.example.com/data');
const data = await response.json();
このデータはその後、Astro.jsのコンポーネントで利用できます。
Astroとほかのフレームワークを組み合わせる
Astroは、ほかのUIフレームワークと組み合わせて使用することが可能です。
例えば、React、Vue、Svelteなどのフレームワークを一つのプロジェクト内で混在させられるので、各フレームワークの長所を活かした開発ができます。
ここからは、具体的にReact、Svelte、Vueを組み合わせて使用する実装例を紹介していきます。
Reactでの実装例
タグ一覧を表示するコンポーネントをReactで実装します。
タグ一覧を取得し、Storeに値を保持したあと、一覧を表示。
また、タグを選択することでそのタグに分類される記事一覧を取得できます。
jsx
import { useStore } from "@nanostores/react";
import { useEffect, useCallback } from 'react';
import { getTags, tags, tag } from "../../store/tagStore";
import { Tag } from './Tag'
export const TagLayout = () => {
const tagList = useStore(tags);
useEffect(() => {
getTags();
}, [])
const handleTagOnClick = useCallback((selectedTag: string) => () => {
tag.set(selectedTag)
}, []);
if (!tagList.length) {
return <div>Now Loading....</div>
}
return (
<div className="tag-list">
{tagList.map((tag) => (
<Tag key={tag} tag={tag} handleTagOnClick={handleTagOnClick(tag)}/>
))}
</div>
);
};
Svelteでの実装例
どの分類の記事一覧を表示するかを管理するコンポーネントを、Svelteで実装します。
選択することで、どの記事一覧を表示するかを切り替えることができます。
svelte
<script>
import { tag } from "../../store/tagStore";
import { userInfo } from "../../store/userStore";
import {
getGlobalArticles,
getArticlesWithRequirements,
} from "../../store/articleStore";
function handleChangeFeedNav(e) {
const name = e.currentTarget.name;
switch (name) {
case "global": {
getGlobalArticles();
break;
}
case "mine": {
getArticlesWithRequirements({ author: $userInfo.username });
break;
}
default: {
getArticlesWithRequirements({ tag: name });
break;
}
}
}
</script>
<div class="feed-toggle">
<ul class="nav nav-pills outline-active">
<li class="nav-item">
<button on:click={handleChangeFeedNav} name="mine" class="nav-link">
Your Feed
</button>
</li>
<li class="nav-item">
<button
on:click={handleChangeFeedNav}
name="global"
class="nav-link"
>
Global Feed
</button>
</li>
{#if $tag}
<li class="nav-item">
<button on:click={handleChangeFeedNav} name={$tag} class="nav-link">
{$tag}
</button>
</li>
{/if}
</ul>
</div>
Vueでの実装例
記事一覧を表示するコンポーネントをVueで実装します。
FeedNavigationでどの記事一覧を表示するかを選択し、一覧を取得して表示できます。
vue
<template>
<div v-if="articles.length">
<ArticlePreview
v-for="article in articles"
v-bind:key="article.slug"
:author="article.author.username"
:date="article.createdAt"
:favCounts="article.favoritesCount"
:title="article.title"
:description="article.description"
/>
</div>
</template>
<script>
import ArticlePreview from './ArticlePreview.vue';
import { getGlobalArticles, postedArticles } from "../../store/articleStore";
import { useStore } from "@nanostores/vue";
export default {
components: {
ArticlePreview,
},
created() {
getGlobalArticles();
},
setup() {
const articles = useStore(postedArticles);
return { articles };
},
};
</script>
これらのコンポーネントはAstroコンポーネントと呼ばれ、ベースとなるテンプレートコンポーネントに組み込まれます。
Astroコンポーネントでは、デフォルトでビルド時にコンポーネント内部のJSが全て実行され、クライアントサイドのランタイムを持たず、HTMLのみのコンポーネントとして表示されます。
そのため、インタラクティブなコンポーネントを扱う際にはclient:*を明示的に指定し、どのようにレンダリング・ハイドレーションされるかを定義する必要があります。
Astro.jsのメリット
パフォーマンスの最適化
Astro.jsは、パフォーマンス最適化に重点を置いています。
ウェブサイトの読み込み速度を向上させるために、静的サイト生成(SSG)やサーバーサイドレンダリング(SSR)などの技術を利用します。
また、Astro.jsはJavaScriptの配信を最小限に抑えるため、ページの読み込みが速くなります。
さらに、画像の遅延読み込みや非同期スクリプトの使用など、他のパフォーマンス向上のテクニックも実装されています。
これらの技術により、SEOの向上とユーザーエクスペリエンスの改善が期待できます。
SEOとアクセシビリティ
Astro.jsはSEOに優れたウェブサイトを作成するのに適しています。
メタデータの管理、構造化データの統合、適切なHTMLセマンティクスの使用など、SEOを強化するための機能が備わっています。
また、アクセシビリティに関しても、キーボードナビゲーションのサポート、スクリーンリーダー対応のマークアップなど、利用者の多様なニーズに対応するための機能が組み込まれています。
これらの要素は、Astro.jsを使用する際の重要な考慮点です。
Astro.jsのサンプルコード
// APIからデータを取得
const response = await fetch('https://api.example.com/posts');
const posts = await response.json();
// 取得したデータをページにレンダリング
posts.forEach(post => {
<article>
<h2>{post.title}</h2>
<p>{post.content}</p>
</article>
});
外部APIから取得したデータを用いて動的なコンテンツを生成する方法を示しています。
このように、Astro.jsではサーバーサイドで動的なコンテンツを生成し、よりインタラクティブでユーザーに合わせた体験を提供することが可能です。
まとめ
Astroを使用する主なメリットは、複数のUIフレームワークを組み合わせた開発が可能となり、それぞれのフレームワークの長所を活かした開発ができることです。
また、Nano Storesを使うことでフレームワーク間での状態管理も容易となります。
複雑な画面構成のウェブアプリの作成をするには少々難易度が上がりますが、アイランドアーキテクチャや複数のUIフレームワークを混ぜて遊ぶことができるAstroを取り入れることで、新しい開発体験を得ることができるでしょう。