シンプルなWebフロントフレームワーク、Astroって知ってる？

:::note warn
この記事の内容は、あくまでも**私個人の意見や好み**の話です。一意見としてお聞きいただければ幸いです。また、時節が変わるにつれて私個人の好みも変わっていくことがありますので、その点は悪しからず。
:::

**[Astro](https://astro.build/)というWebフロントエンドのフレームワーク**をご存知でしょうか。自分も最近知って使うようになり、とても気に入ってしまったので、その紹介をしていきたいと思います。

## Astroを知る前
**Webフロントエンドのフレームワーク**といえば皆さんは何を思いつきますか。Vue, React, Svelteなどなどいろいろとあるかと思います。私も最近はほとんどReactを使って開発をしていました。

ただそんな中で感じていたのは、**ちょっとした静的なページを作りたいときに、React使うのは重たいなぁ**といった感覚です。APIと頻繁にデータをやり取りするだとか、ログイン機能があるだとか、そういう所謂**Webアプリ**であればReactで実装するのはやりやすいです。でも、たとえばブログとかポートフォリオとか、そういった**静的ページ**を作りたいだけなのにReactのSPAが必要かと言われるとうーん、と思います。

でもだからって、バニラのHTMLやJSを使うかと言われるとそれも不便です。不便だからReactに逃げてきた訳です。

## どんな機能が欲しかったのか
じゃあどんな機能が欲しいのか、Reactほどリッチではなくていいけど、バニラのHTMLとJSで物足りないことは何なんでしょうか。私にとっての答えは主に下の2つでした。

- **コンポーネント**の概念
- **JSX**のような**テンプレートエンジン**

サイトで使うヘッダーだとかボタンだとか、そういった**部品をコンポーネントとして分けて実装**し、**責務を分離したり再利用可能にしたりする**というのは、最近のWeb開発では一般的なことなのかなと思います。Reactのようなフレームワークだとやっぱりそれができるのが一番嬉しいです。同じコードを繰り返し書く手間が省けます。修正があっても1箇所で済みます。

バニラのHTMLにも[Web Components](https://developer.mozilla.org/ja/docs/Web/API/Web_components)という概念があることは聞いたことがありました。ただ、あまり一般的ではない印象ですし、その分学習コストや参考になるドキュメントも少ないのかなーと感じてしまいます…。

次の**JSX**というのはReactでも利用されていることで有名ですね。**HTMLライクにタグを書いていき、一部でJSの式や値を参照できる**という記法です。たとえば以下みたいにすれば、JSの変数`name`がHTMLの中に展開されてレンダリングされます。

```jsx
var name = "mochi";

return (
  <div>
    <p>{name}</p>
  </div>
);
```

**JSの文法さえ分かれば**for文で要素を繰り返し表示したり、`Array.map()`で配列をリストとして表示したりといったことも容易に行えます。大学の授業でバニラのJSの`getElementById()`みたいなDOM操作を習いましたが、JSXの方が圧倒的に楽です…。

特に最近のIDEなら補完が効くのも嬉しい点です。JSのstring型でHTMLをいっぱい書いて、element.innerHTMLに代入するとかにはもう戻れない気がします。

「JSの文法さえ分かれば」というのを強調しているのは、Vueの`v-for`のような**独自の書き方**を意識してのことです。私も初めはVueを使っていましたが、Vueだけでしか使えない`v-for`のような独自の書き方を学ぶのが、他に応用することができず少々面倒くさいなーと感じてしまいました。

Reactにも`useState`とか`useEffect`とか特有の機能はありますが、基本的なことはHTML/CSS/JSと似た書き方で扱えます。これは、初めのハードルとして低いのかなと思っています。

そんなこんなで**コンポーネント**と**JSX**が良くて最近はReactを使うことが多かった訳ですが、それでも**静的サイト**を作るには少しリッチすぎると感じてしまいます。

先ほどもあげた`useState`とか`useEffect`とかのような機能は、静的サイトじゃまず使いません。ルーティングを設定するのにもたとえば`react-router-dom`で設定して、生成されたものはSPAの形になります。そこまでは要らないんだけどなぁー。

Reactみたいなコンポーネントとかテンプレートエンジンが使えて、シンプルに静的サイト作れるフレームワーク。そんな都合の良いものないかなー。

## Astroがありました
ありました。[Astro](https://astro.build/)というものです。たとえば**JSXのような以下のような書き方**ができます。また、以下の要素を**コンポーネントとして使い回す**こともできます。もちろんコンポーネントのpropsなども設定可能です。それが非常にシンプルなHTML/JS/CSSっぽい書き方で書けています。これに出会って開発してみると、「あぁ、僕が求めていたものはこれだ」なんて気持ちになりました。

```jsx:sample.astro
---
const name = "mochi"
---

<div>
  <p>{name}</p>
</div>
<style>
  p {
    color: red;
  }
</style>
```

詳細なドキュメントは[公式サイト](https://docs.astro.build/ja/getting-started/)に投げますが、いくつか特に好きな点を挙げておきます。

https://docs.astro.build/ja/getting-started/

### `Content-driven`という設計思想

https://docs.astro.build/en/concepts/why-astro/#design-principles

設計思想として、ログインなどの伴う**Webアプリケーション**を構築するフレームワークではなく、コンテンツが主体のブログのような**Webサイト**を構築するフレームワークであるとしています。もう、まさに自分の求めていたものでした。

### ファイルベースのルーティング

https://docs.astro.build/en/guides/routing/

Next.jsのApp Routerを使ったことのある方にはお馴染みの**ファイルベースのルーティング**になっています。`src/pages/`ディレクトリ以下のファイルがURLのパスにそのまま対応します。`src/pages/photo.astro`というファイルがあれば、URLの`/photo`にレンダリングされます。

`react-router-dom`のような設定方法だと、ページが増えるたびにルータの設定も修正する必要があるなど面倒だなーと思っていました。このファイルベースのルーティングであれば、そうした追加の設定などが不要になり便利だなと思っています。

### Vueの単一ファイルコンポーネントのような書き方とスタイルのスコープ

https://docs.astro.build/en/basics/astro-components/

先ほど挙げたAstroのコンポーネントのサンプルを見て、**Vueの単一ファイルコンポーネント**のようだと感じた方もいるかと思います。自分がAstroで開発する時は、このようにスクリプト部、HTML部、スタイル部と分けて記述をしています。昔Vueを書いていた名残りかもしれません…。ただ、こうすることで、**この1つのファイル内にそのコンポーネントの実装が集約される**というのは嬉しいなと感じる点です。

:::note warn
ここでのスクリプト部に書かれた処理は、**ビルド時に1度だけ実行**されます。毎回のページ表示時にクライアント側で実行されるものではないことにご注意ください。 [参考](https://docs.astro.build/en/guides/data-fetching/)
:::

また、この例では`<style>`タグを使って`<p>`要素のスタイルを指定しています。このとき、このスタイルは**このコンポーネント内のみのスコープ**になります。すなわち、ここで`color: red;`と設定していても、他のコンポーネントの`<p>`タグでは普通の色で表示されます。このように意識せずにスタイルのスコープを制限できるという機能は非常に嬉しいなと思っています。

```jsx:sample.astro（再掲）
---
const name = "mochi"
---

<div>
  <p>{name}</p>
</div>
<style>
  p {
    color: red;
  }
</style>
```

### Reactのコンポーネントを再利用したり、Markdownをそのままページとしてレンダリングできたりする

https://docs.astro.build/en/guides/framework-components/

今までReactなどで作ってきたコンポーネントがある場合、それを**そのまま再利用**することが可能です。こうしたReactのコンポーネントであれば、クライアント側で実行される処理をスクリプトとして書くことも可能です。React以外にもSvelteやVueなどのフレームワークも公式で対応されています。

https://docs.astro.build/en/guides/markdown-content/

Markdownのファイルをそのままページとして表示することができます。また、**Markdown用のレイアウト**を作って、それを適用してページを表示するといったことも可能です。たとえばこのQiitaの記事も	Markdownで書いていますが、それをそのままフォルダに置けばブログ記事のように表示されますよ言われれば、非常に便利です。

## おわりに
そんなこんなで[Astro](https://astro.build/)の紹介をしてきました。ぜひ皆さんも、一度お使いになってみてはと思います。よいAstroライフを👋

## 参考

https://qiita.com/hedrall/items/f2ebb5338f79007083a3

https://developer.mozilla.org/ja/docs/Web/API/Web_components

https://zenn.dev/kagan/articles/ad0e327db0265a