初心者がサクッと学ぶAstro

みなさんよくWeb制作をすると思います。やはり楽に制作を進めたいので何かしらのフレームワークを使用する機会が非常に多いものです。しかし、ちょっとしたブログやランディングページを作りたいときにReact.jsやVue.jsを使用するのはオーバースペックだと思ったことはありませんか。
Web制作では速度などのパフォーマンスが重視されます。それに対し先程のフレームワークではSPAであり、決して初回のロード時間が早くありません。こういう場合には各ページのロードが早いMPAにしたいです。
そんな場合におすすめできるフレームワークがAstro.js(以下Astroという)です。理由は次章で紹介します。
## Astroとは
Astroについてもっと詳しく知りたければ、ネットを探せばいくらでもあると思います。
### JavaScript
AstroはゼロJSを目標にしており、余計なJavaScriptが生成されません。Astro内に書かれたJavaScriptはビルド時に実行され、HTMLに変換されます。そのため、クライアントでのコード実行が必要なく非常に軽いページを作れます。
Astroでは専用のスペースにJavaScriptを書くだけでなく、いわゆるJSXのような記法でJavaScriptを書きます。
もちろんクライアント側で実行するJavaScriptを埋め込むことも可能です。
### コンポーネント
Astroはコンポーネント指向のためコードの使い回しが可能です。たとえばヘッダーコンポーネントを作れば、全てのページに同じヘッダーを適用できます。フレームワークを常用する人にとっては欠かせない機能でしょう。
### アイランドアーキテクチャ
Astroアイランドという仕組みで、様々なUIフレームワークをAstro内で使うことができます。たとえばReact, Vue, SvelteなどのUIフレームワークをサイト内に埋め込むことで、慣れた言語で実装したりWebアプリにしたりするために使います。他の使用可能なUIフレームワークについては公式ドキュメントを見てください。
### Markdown
Markdownをそのまま取り込んで描画することが可能です。自動的にHTMLに変換され、CSSを適用できます。実際にブログなどを作るときはこの機能が使えるでしょう。


## 機能
Astroで使える素晴らしい機能の解説です。
### JavaScript
Astroでは2種類のJavaScriptが使用できます。1つはビルド時に実行して静的ファイルに変換するもので、もう1つはHTMLで使うようなscriptタグです。
今解説するのは前者のJavaScriptです。まずは簡単なコードの例を見てみます。
```jsx
---
const text = "Hello, World!";
---
<p>{text}</p>
```
前ページのAstroコードを実際にブラウザで表示してみるとpタグで「Hello, World!」とレンダリングされます。今の状態だとあまりメリットを感じないかもしれません。私がよく使う使い方は以下のようなコードを書きたいときです。
```html
<ul>
<li class="content border" id="apple">りんご</li>
<li class="content border" id="banana">ばなな</li>
<li class="content border" id="grape">ぶどう</li>
</ul>
```
この場合「めろん」など新しい項目を追加するのも大変ですし、`class`の内容を変更することになったら3つとも変更しなければなりません。
HTMLで解決できないことはありませんが、Astroだともっとスマートに可能です。
```jsx
---
const fruits = [
  {
    id: "apple",
    name: "りんご",
  },
  {
    id: "banana",
    name: "ばなな",
  },
  {
    id: "grape",
    name: "ぶどう",
  },
];
---
<ul>
{
  fruits.map((fruit) => (
    <li class="content border" id={fruit.id}>{fruit.name}</li>
  ))
};
```
前ページのコードのようにコンテンツを配列やオブジェクト形式で管理してHTMLに変換することで、コードをシンプルに読みやすく書きやすくできます。
先程の例だとコードの行数は逆に増えてしまっていますが、もっと規模の大きいWeb制作をしていくときにはメニューやリストに使用し、コードを大幅に削減できました。

実はここではTypeScriptを使うことができます。Astroプロジェクト作成時に対話型で`Do you plan to write TypeScript?`と聞かれるのでYesと答えればTypeScriptに対応します。TypeScriptが分かる人であれば`Astro.props`という怪しい型さえ覚えれば問題なく使用できると思います。
### scriptタグ
じゃあ動的な動作はどうしたらいいのかというと、それはHTMLと何も変わりません。
```html
<script>
  window.alert("Hello, World!")
</script>
```
このように書けば「Hello, World!」とアラートされます。「じゃあこれはいつものscriptタグなんだな」と思うかもしれませんが、実は微妙に違う挙動をします。
Astroのscriptタグはすべてheadタグの中にtype="module"埋め込まれます。そのため常に遅延読み込みされ、asyncやdefer属性は使用されません。
scriptタグの中に書かれたTypeScriptは自動的にトラスコンパイルなどの処理がされます。`node_modules`をscriptタグから読み込むことも可能になっているわけです。
これらの処理のおかげで、コンポーネント内にscriptタグを置きそのコンポーネントを複数並べたとしてもscriptタグ自体は1つのみ生成されます。場合によってはこの処理がじゃまになる機会があります。その際はscriptタグに`is:inline`属性をつければ皆さんのよく知るscriptタグになってくれます。

ちなみに以下のコードのように書くことで、静的なJavaScriptからscriptタグの中身へと変数の受け渡しができる機能が存在します。
```jsx
---
const text = "Hello, World!";
---
<script define:vars={{text}}>
  window.alert(text);
</script>
```
### styleタグ
皆さんもお気づきの通りstyleタグも特殊です。ただscriptタグほどクセは強くなく、非常にシンプルなものです。
コンポーネント内に書かれたstyleタグのCSSはそのコンポーネントのHTMLにしか効果がないというものです。ここで指定したCSSがあっちのコンポーネントに適用されてしまうなんてことは起こりません。
もちろん全体に適用したいときにも対応していて、`is:global`属性をつけることができます。
SCSSを使用することもとても簡単です。
```bash
npm install -D sass
```
これを実行するだけでAstroはSCSSに対応するようになります。ただscriptタグのときと違い`lang="scss"`と属性で言語を指定する必要があることに注意です。
変数はscriptタグとほぼ同じなので割愛します。

読み込んでいるコンポーネントに対してCSSを適用したいときがあるでしょう。
```html
<Card class="card">
  <p>Hello, World!</p>
</Card>
```

実際にこのように`class`を与えてみると`プロパティ 'class' は型 'IntrinsicAttributes & Props' に存在しません。`と怒られてしまいました。これはTypeScriptを使っているため発生したエラーで、JavaScriptだと発生しません。けれどもいざCSSを適用しようとすると、効果が現れません。
`Card`コンポーネント側にコードを指定する必要があります。
```jsx
---
const { class: className, ...rest } = Astro.props;
---
<div class={className} {...rest}><!-- 好きなコード --></div>
```
`class: className`のように遠回しな指定をした理由は`class`がJavaScriptの予約語であるため使用できないからです。
`...rest`は`Card`コンポーネントに与えられた属性をすべてオブジェクト形式にしています。それを子コンポーネントに送りスコープしています。多分他の方法があるはずです。

## 参考文献

https://docs.astro.build/ja

https://zenn.dev/morimichi/articles/44ed403123e5a9