Site cover image

ふつうのITエンジニアの独り言

本業はAndroidとiPhoneのアプリ開発のエンジニアです。将来はフリーランスで海の近くで妻とのんびり暮らすことを夢見て、幅広くIT技術に触れていきたいと思います。このブログはその備忘録と私のポートフォリオとして活動記録を記すものです。

astroを基本から学び、astro-notion-blogを理解したい(その2) ~Astroのディレクトリ構成と基本ルールを学ぶ~

目次


ディレクトリ構成に関して


 Astroは、.astroのファイルにHTMLコードを記述することになるが、他にもスタイルシートのCSSやマークダウンのmdファイルなども扱える。基本的なディレクトリ構成は公式で確認することができる。

src/pages/

 このディレクトリがページルーティングのルートになり、この下に置かれた.astroファイルがWebページとして公開される。たとえば、pages/posts/index.astroを用意すると、”https://www.xxx.com/posts/index”がURLとなって公開されることになる。

 ルーティングには、静的ルーティングと動的ルーティングがあり、動的ルーティングを使うとビルド時に事前に用意したリストを元に複数のページが作られる。

src/components/

 Astroでは、コンポーネントを入れ子にしてコンテンツを構成することができ、そのコンポーネントを管理するためのディレクトリ。必ずしもcomponentsである必要はなく、慣習的なものだそうだ。

src/layouts/

 UIレイアウトを定義するファイルを管理するディレクトリ。レイアウトファイルには必ずslotタグがHTLMコードに埋め込まれていなければならない。こちらもlayoutsは慣習的な命名で、特にルールはない。

<slot />

src/styles/

 スタイルシートを管理するディレクトリ。こちらも慣習であってstylesでなくてよい。

public/

 fabconや画像などのファイルを置く場所として利用すると良い。ここにコードをおいてもビルドされないので置かないこと。

.astroファイルの基本ルール


フロントマターとHTMLコード

 astroのプロジェクトを新規作成すると、src/pages/index.astroのファイルが自動生成されており、フロントマターと呼ばれる領域が用意されているのがわかる。また、フロントマターより下には通常のHTMLタグを用いたコードを記述することができる。

---
// "---"で囲われたこのスペーズは、フロントマター(frontmatter)と呼ばれる領域。
// ここには、JavaScriptを書くことができる。
// astroが静的コンテンツをを生成するさいに実行され、公開されるWebページには含まれない
---

<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
		<title>Astro</title>
	</head>
	<body>
		<h1>Astro</h1>
	</body>
</html>
src/pages/index.astro

変数の定義と利用

HTML内での利用

 フロントマターで定義した変数は、HTMLコードで利用することができる。以下は、titleタグとh1タグの要素の内容を変数化すると次のように記述できる。

---
const pageTitle = "ページのタイトル";
const name = "Astro";
---

<html lang="en">
	<head>
		~省略~
		<title>{pageTitle}</title>
	</head>
	<body>
		<h1>{name}</h1>
	</body>
</html>
src/pages/index.astro
Script内での利用

 フロントマターで定義した変数をscriptタグの中で利用することもできるが、”define:vars”を宣言しておく必要がある。また、”define:vars”を使った場合、script内はTypeScriptではなくJavaScriptとなることも覚えておきたい。

<script define:vars={{ name, pageTitle }}>
	console.log(`name=${name} pageTitle=${pageTitle}`);
</script>

コンポーネントの利用

 Astroでは、.astroで作成したコンポーネントを別の.astroのHTMLの中に埋め込むことができる。

graph LR
	subgraph Page[Page.astro]
		HTML("HTML要素")
	end
	
	subgraph HTML[HTML要素]
		COMP("(コンポーネント)ダグ")
	end
	
  Component("(コンポーネント).astro") --> |import|COMP
コンポーネントをHTMLに埋め込むイメージ

 試しに、headタグ部分をコンポーネントとして切り出す。”src/components”に”Header.astro”ファイルを作成し、index.htmlのheadタグをコピペする。コンポーネントには任意の値を渡すことができ、Astro.propsから受け取れる。

----
// コンポーネントを利用する側から渡されたパラメータを受け取ることができる。
// ここでは、ページタイトルを受け取る
const { pageTitle } = Astro.props;
----

<head>
	<meta charset="utf-8" />
	<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
	<meta name="viewport" content="width=device-width" />
	<meta name="generator" content={Astro.generator} />
	<title>{pageTitle}</title>
</head>
src/components/Header.astro

 コンポーネントを利用する.astro側では、先ほど作成したHeaderコンポーネントを読み込み、HeaderタグをHTMLに埋め込んで使う。この様にheaderタグ要素を複数のページで使い回せるようになる。headerタグだけでなく、あらゆるHTML要素を、再可能なコンポーネントにできる。

---
// Headerコンポーネントをimport
import Header from "../components/Header.astro"

const name = "Astro";
---

<html lang="en">
	<!-- インポートしたHeaderタグを記述し、pageTitleをHeaderコンポーネントに渡す -->
	<Header pageTitle={"ページのタイトル"}/> 
	<body>
		<h1>{name}</h1>
	</body>
</html>
src/pages/index.astro

レイアウトの利用

 レイアウトもコンポーネントと同じように再利用できるが、コンポーネントとは少し使い方が異なる。レイアウトにはあらかじめslotタグを埋め込んでおき、そのslotタグを任意のHTML要素に置き換えて利用するという使い方をする。このとき、置き換えるHTML要素にはコンポーネントも使える。

graph LR
	subgraph Page[Page.astro]
		HTML1
		SLOT1("HTML要素
		       (コンポーネントも可)")
	end
	
	subgraph HTML1["HTML要素"]
		LAY("(レイアウト)タグ")
	end
	
	
	subgraph Layout["(レイアウト).astro"]
		HTML2
	end
	
	subgraph HTML2["HTML要素"]
		SLOT2("slotタグ")
	end
	
	Layout --> |import|LAY
	SLOT1 --> |slotタグ書き換え|LAY
レイアウトを埋め込み、slotを他の要素に書き換えるイメージ

 試しに、実装してみる。BaseLayout.astroを用意する。

---
const { name } = Astro.props;
---

<html lang="en">
	<slot/>
	<body>
		<h1>{name}</h1>
	</body>
</html>
src/layouts/BaseLayout.astro

 BaseLayoutをindex.astroで利用するには、フロントマターでBaseLayoutを読み込み、BaseLayoutタグを埋め込む。その要素に、slotと差し替えたいコードを記述すれば良い。サンプルでは、Headerタグの一行だけを渡しているが、BaseLayoutの要素には自由にタグを記述できる。

---
// BaseLayoutをimport
import BaseLayout from "../layouts/BaseLayout.astro"

// Headerコンポーネントをimport
import Header from "../components/Header.astro"

const name = "Astro";
---

<BaseLayout name = {name}>
	<Header pageTitle={"ページのタイトル"}/> <!-- pageTitleをHeaderコンポーネントに渡す -->

</BaseLayout>
src/pages/index.astro

まとめ


 初期生成時のindex.astroと表示内容に変わりはないが、レイアウトとコンポーネントを使っても同じように表示できる。レイアウトとコンポーネントを使うことで、複雑なコードや繰り返して使うものを別ファイルにして開発することが出来るので、非常に保守性に優れていると感じられた。次回は、マークダウンと、ページの自動生成に付いて学んで行きます。