今回は以前構築したPodman + Astroの開発環境を使って、実際にWebサイトのトップページを構築してみます。
前回の記事: https://vpslife.server-memo.net/podman_astro_install/
Astro開発サーバ起動
まずは、作業用のコンテナ(開発サーバー)を起動します。
$ cd ~/project/astro-dev $ podman-compose up -d
Astroプロジェクトのディレクトリ構造
Astroでは、「src」ディレクトリが、これからWebサイトのページ等を作成していくメインの作業場所となります。
Astroでビルドコマンド(npm run build)を実行すると、この「src」ディレクトリの中身を読み込んで最適化し、本番公開用の最終的なHTMLファイルを作成してくれます。
インストール直後のsrcディレクトリ
インストール直後の「src」ディレクトリ内は、以下のような構造になっていて、役割ごとにディレクトリが分かれています(必要に応じて自分で追加作成します)。
./astro-dev/src/
├── assets/
│ ├── astro.svg
│ └── background.svg
├── components/
│ └── Welcome.astro
├── layouts/
│ └── Layout.astro
└── pages/
└── index.astro
各ディレクトリの役割を解説します。
src/assets (画像やCSSなど)
画像やCSSファイルを格納する場所です。
ここに置いた画像やCSSファイルは、ビルド時にAstroが自動的にファイルサイズを圧縮したり、ブラウザのキャッシュが効きやすい名前に最適化してくれます。
※プロジェクトの直下にあるpublicディレクトリも画像を格納する場所ですが、あちらはAstroが加工せずにそのまま配信するファイルを格納する場所です。
src/components (部品・コンポーネント)
サイト内で何度も使用する「UIの部品」を格納する場所です。
ヘッダー、フッター、ボタンなどを、それぞれ「.astro」ファイルとして作成しておきます。
src/layouts (レイアウト・ひな形)
ページ全体の大枠(テンプレート)を格納しておく場所です。
HTMLの基本構造(<html>、<head>、<body>)や、全ページ共通のヘッダーやフッターの配置をここで定義しておきます。
src/pages (ページとルーティング)
Webサイトの各ページとなるファイルを作成する場所です。
ここに置いたファイル(.astro、.md、.html など)の構成が、そのままWebサイトのURLになります。
- src/pages/index.astro localhost:4321/ (トップページ)
- src/pages/about.astro localhost:4321/about/ (アバウトページ)
- src/pages/blog/first-post.md localhost:4321/blog/first-post/ (ブログ記事)
src/content(コンテンツコレクション)※新規作成が必要
ブログ記事などMarkdown形式(.md)で書いた記事をまとめて管理する専用のディレクトリです。(初期状態では存在していないので、自分で作成する必要があります)
事前に「スキーマ」と呼ばれるルールの設定書を用意しておくことで、Astroが「記事のタイトルが入力し忘れられていないか」「日付の形式が間違っていないか」などを厳密にチェックしてくれます。
また、この機能を使うと「最新の記事一覧表示」などが非常に簡単に実装できるようになります。
トップページ(index.astro)の編集
それでは、実際に「src/pages/index.astro」ファイルを編集してみます。
$ cd ~/project/astro-dev/src/pages $ vi index.astro
初期状態で作成されている「index.astro」ファイルを編集し、お約束の「Hello World」を追加してみました。
---
import Welcome from '../components/Welcome.astro';
import Layout from '../layouts/Layout.astro';
// Welcome to Astro! Wondering what to do next? Check out the Astro documentation at https://docs.astro.build
// Don't want to use any of this? Delete everything in this file, the `assets`, `components`, and `layouts` directories, and start fresh.
---
<Layout>
<h1>Hello World!!</h1>
<Welcome />
</Layout>
ファイルを保存してブラウザで(http://localhost:4321)を確認すると、リロード(更新)ボタンを押さなくても、保存した瞬間に変更が反映されました!
Astroのホットリロード機能、ちょっと感動しますよね。
トップページを作成する
公式のサンプルコードの動作が確認できたので、今度は中身をすべて消して、自分のブログ用のトップページを1から作成してみます。
Astroファイル(.astro)のコードの仕組み
Astroファイル(.astro)は、大きく2つのパーツで構成されています。
上部(--- で囲まれた部分)
ここは「コンポーネントスクリプト」と呼ばれ、サーバー側で動くJavaScriptやTypeScript(変数の定義など)を書きます。
変数名はJavaScriptの標準的な文化である「キャメルケース」(ペースを使わずに複数の単語を連結し、2語目以降の先頭を大文字にする命名規則)で定義するのが一般的です
今回は「siteName」という変数にサイト名を入れています。
ここの処理結果はブラウザには表示されず、サーバー側(ビルド時)で実行されます。
下部(HTML部分)
実際の画面の骨組みです。
普通のHTMLとほぼ同じですが、上部で作った変数を {siteName} のように波括弧 { } で囲むだけで、簡単に文字をHTML内に埋め込むことができます。
新しいindex.astroの作成
「index.astro」の中身を、以下の内容に書き換えます。
今回はサイト名を「Game Life」として作成してみます。
---
// ここは「コンポーネントスクリプト(Component Script)」と呼ばれる部分です。
// サーバー側で動くJavaScriptやTypeScript(変数の定義など)を書きます。
// 変数名はJavaScriptの標準的な文化である「キャメルケース」を使って変数を定義
const siteName = "Game Life";
const description = "ゲームに関することを書いていきます。";
---
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="description" content={description} />
<title>{siteName}</title>
</head>
<body>
<header>
<h1>{siteName}</h1>
<nav>
<a href="/">ホーム</a>
<a href="/blog/">ブログ</a>
</nav>
</header>
<main>
<h2>こんにちは!</h2>
<p>AstroとPodmanで構築した新しいブログ環境へようこそ。</p>
<p>ここはトップページ(index.astro)です。これからここに、最新の記事一覧などを表示させていきます。</p>
</main>
<footer>
<p>© 2026 {siteName}</p>
</footer>
</body>
</html>
編集し保存すると、内容が即時に反映されます。
ヘッダーとフッターをコンポーネント(部品)化する
次に、全ページの共通で使用する「ヘッダー」と「フッター」部分を切り離して、再利用できるようにコンポーネント(部品)化してみます。
コンポーネント化するための部品は「src/components」ディレクトリに作成します。
ヘッダー作成(Header.astro)
今回は、「src/components/Header.astro」というファイルを作成し、以下のコードを記述します。
---
const siteName = "Game Life";
---
<header>
<h2><a href="/">{siteName}</a></h2>
<nav>
<a href="/">ホーム</a>
<a href="/blog/">ブログ</a>
</nav>
</header>
<style>
/* CSSもここで書けます */
header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #ccc;
padding: 10px 20px;
}
nav a {
margin-left: 15px;
text-decoration: none;
color: #333;
}
</style>
フッターの作成 (Footer.astro)
「src/components/Footer.astro」という名前でフッター部分を作成します。
ここでは少し工夫して、Copyrightで表示される「年」を自動で取得する機能をつけてみます。
todayという変数に現在の日付を代入し、「{today.getFullYear()}」で年を取得して表示させています。
---
// サーバーがページを生成した時の「現在の日付」を取得します
const today = new Date();
---
<footer>
<p>© {today.getFullYear()} Game Life. All rights reserved.</p>
</footer>
<style>
footer {
text-align: center;
padding: 20px;
margin-top: 40px;
border-top: 1px solid #eee;
color: #666;
}
</style>
index.astroでヘッターとフッターを読み込ませる
作成したヘッダーとフッターの部品を呼び出すように、トップページ(index.astro)を修正します。
上部のコンポーネントスクリプト部分で「import」を使用し、ヘッダーとフッターを読み込ませます。
そして、下部のHTML部分でヘッダー挿入したい部分に「<Header />」、フッターを追加したい部分に「<Footer />」を記述します。
---
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
const description = "ゲームに関することを書いていきます。";
---
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="description" content={description} />
<title>Game life</title>
</head>
<body>
<Header />
<main style="padding: 20px;">
<h2>こんにちは!</h2>
<p>AstroとPodmanで構築した新しいブログ環境へようこそ。</p>
<p>ヘッダーとフッターが「コンポーネント」として分離されました。</p>
</main>
<Footer />
</body>
</html>
これでトップページが作成されました。
<head>部分もコンポーネント化したい
トップページは完成しましたが、<head>部分も全ページほぼ共通の記述になるため、今後を見据えてコンポーネント化してしまいます。
ここで注意が必要なのが、「titleやdescriptionはページによって変更したい」という点です。
トップページなら「Game Life」、ブログ記事なら「記事のタイトル」といったように、中身を動的に変える必要がありますよね。
Astroでは、「Props(プロップス:引数)」という仕組みを使うことで、この点をスマートに解決できます。
BaseHead.astro(<head>部分)を作成
「src/components/」ディレクトリに、「BaseHead.astro」というファイルを以下の内容で作成します。
---
// 「Astro.props」を使って、呼び出し元からデータを受け取ります
const { title, description } = Astro.props;
---
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{title}</title>
<meta name="description" content={description} />
index.astroでBaseHeadを読み込ませる
「index.astro」を編集して、BaseHeadの読み込みと<head>部分にBaseHead表示させる設定を追加します。
---
import BaseHead from '../components/BaseHead.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
const siteName = "Game Life";
const description = "ゲームに関することを書いていきます。";
---
<html lang="ja">
<head>
<BaseHead title={siteName} description={description} />
</head>
<body>
<Header />
<main style="padding: 20px;">
<h2>こんにちは!</h2>
<p>AstroとPodmanで構築した新しいブログ環境へようこそ。</p>
<p>head部分もコンポーネント化しました!</p>
</main>
<Footer />
</body>
</html>
データの受け渡し(Props)の仕組み
「index.astro」で下記のように記述することで、タイトル(title)と説明文(description)に使用する内容を、コンポーネント(部品)側へパス(渡す)することが出来ます。
<BaseHead title={siteName} description={description} />
パスされた内容は、「BaseHead.astro」の「Astro.props」で受け取ることができます。
const { title, description } = Astro.props;
共通レイアウト(BaseLayout.astro)を作成する
これまで作成してきた「Header.stro」「Footer.astro」「BaseHead.astro」を1つにまとめた、全ページ共通の雛形(レイアウトファイル)を「src/layouts/」ディレクトリに作成します。
このレイアウトを作成することで、今後はスクリプトコンポーネント部分と数行のコードと本文を書くだけで、新しいページを作成することが出来るようになります。
レイアウトファイル(BaseLayout.astro)を作成
今回は「BaseLayout.astro」という名前でレイアウトファイルを作成していきます。
---
// これまで作った3つの部品をすべて読み込みます
import BaseHead from '../components/BaseHead.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
// このレイアウトを使うページからタイトルと説明文を受け取ります
const { title, description } = Astro.props;
---
<html lang="ja">
<head>
<BaseHead title={title} description={description} />
</head>
<body>
<Header />
<main style="padding: 20px;">
<slot />
</main>
<Footer />
</body>
</html>
<slot />について
このレイアウトを使って新しいページを作る時、そのページで書いた独自の文章や画像が、すべて自動的にこの
<slot />の部分に挿入されて表示される仕組みになっています。
index.astroをレイアウトを使って書き換える
作成したレイアウトファイル(BaseLayout.astro)を使用するように、トップページ(index.astro)を編集します。
---
// 先ほど作った「BaseLayout(最強のひな形)」だけを読み込みます
import BaseLayout from '../layouts/BaseLayout.astro';
// このトップページ用のタイトルと説明文を定義します
const pageTitle = "Game Life トップページ";
const pageDescription = "Game Lifeのトップページです。最新のゲーム情報をお届けします。";
---
<BaseLayout title={pageTitle} description={pageDescription}>
<h2>こんにちは!</h2>
<p>AstroとPodmanで構築した新しいブログ環境へようこそ。</p>
<p>「BaseLayout」を使用することで、ページの作成がより簡単になりました!</p>
<p>この文章は、レイアウトの<slot />(スロット)に自動的に挿入されています。</p>
</BaseLayout>
とりあえず今回はここまでとします。







コメント