Astroで高速Webサイトを簡単に！遅いサイト作成はもう過去の話

# はじめに

初めまして！[システムアイAdvent Calendar 2023](https://qiita.com/advent-calendar/2023/systemi23) 23日目の担当です。

何を書こうかと考えていましたが、良い機会なので今年よく名前を聞き、気になっていたAstroについて学びながら記事を書いてみることにしました。

# Astroとは？
皆さん、Astroをご存知ですか？
2022年6月8日に正式版がリリースされた比較的新しいWeb開発フレームワークです。
執筆時点でのGitHubのスター数は37.9kと、非常に注目されています。

最近では、2023年12月5日にv4.0.0がリリースされました。

https://astro.build/blog/astro-4/

Astroは、高速な静的サイト（SSG）作成に特化したWeb開発フレームワークです。
ビルド時にJavaScriptを最小限（デフォルトでは全て）に削減し、高速なパフォーマンスを実現しています。

また、MPA（Multi-Page Application）を採用し、クライアントサイドレンダリングよりもサーバーサイドレンダリングを優先することで、ユーザーの環境に左右されない一貫したパフォーマンスと初期描画の高速化を実現しています。

Astroは、その特性からコンテンツ重視のWebサイト作成に適しており、主に以下のような用途に向いています。
- マーケティングサイト
- コーポレートサイト
- プログ
- ポートフォリオ

一方で、AstroはWebアプリケーション作成には向いていません。
公式ドキュメントでは、次のように述べられています。

> もし、プロジェクトが2番目の「アプリケーション」に該当する場合、Astroはプロジェクトに適していないかもしれません…… それでもいいのです！ よりアプリケーションに特化した選択肢としては、Next.jsをチェックしてみてください。


# Astroの特徴

### 1. 学習コストが低く簡単にサイトを構築出来る。
Astroは独自の`.astro`UI言語を使用しますが、この言語の書き方はReactのJSXと非常に似ています。

以下は、Astroで最初に生成されるファイルの例です。

``` jsx
---
// ここにJavaScriptを書いていく
---

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

このコードでタイトルを変数に置き換えると以下のようになります。

``` jsx
---
// ここにJavaScriptを書いていく

const title = "Astro"
---

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

Astroの`.astro`ファイルでは、`---`という記号を使ってHTML構造からJavaScriptを記述する部分を分離し、明示します。これは「**フロントマター区切り**」と呼ばれる概念です。

上記のコード例では、フロントマター区切り内で変数`title`を宣言しています。その後のHTML部分では、`{}`を使用してこの変数を埋め込んでいます。この書式はReactのJSXに似ており、Reactの経験がある方には馴染みやすい形式です。

またAstroはコンポーネントベースのフレームワークで、ReactのPropsのように値をコンポーネントに渡すことが可能です。

``` jsx:h1.astro
---
const { text } = Astro.props;
---
<h1>{text}</h1>
```

``` jsx:index.astro
---
// 作成したファイルをインポートする。
import H1 from '../components/h1.astro';

---

<html lang="en">
  <head>
    <title>Astro</title>
  </head>
  <body>
    <H1 text={"Astro"} />
  </body>
</html>
```

上記の例では`src/components/`に`h1.astro`というファイルを作り、`index.astro`でインポートしています。Astroのpropsは`Astro.props`から受け取ります。

Reactを触ったことがある方ならすんなりと書くことが出来るのではないのでしょうか？

しかし、AstroはReact、Preact、Svelte、Vue、Solid、Litなど、複数のUIフレームワークをサポートしています。これにより、エンジニアは慣れ親しんだフレームワークを使用してコーディングする事ができ、学習コストを削減できます。

また、マークダウンをコンポーネントとして扱うことも可能です。

複数のフレームワークを同時に使用することもでき、以下のようなカオスなコードも実現可能です。

``` jsx
---
import Header from '../components/Header.jsx';
import Footer from '../components/Footer.vue';
import Sidebar from '../components/Sidebar.svelte';
import MarkdownContent from '../pages/index.md';
---

<Header />
<Sidebar />
<main>
  <MarkdownContent />
</main>
<Footer />

```

なぜこのような事ができるのかは次で説明します！

### 2. Astroアイランド

アイランドアーキテクチャは、2019年にEtsyのフロントエンドアーキテクトであるKatie Sylor-Miller氏によって考案され、Preactの作者であるJason Miller氏の[ブログ](https://jasonformat.com/islands-architecture/)で広まりました。Astroはこのアイランドアーキテクチャを採用しています。

アイランドアーキテクチャでは、Webサイトを静的なコンテンツと動的なコンテンツに分け、動的なコンテンツは独立した「アイランド」として表示されます。この分離により、動的な部分にのみJavaScriptが適用され、サイト全体のJavaScriptの量を減らし、パフォーマンスを向上させます。

![islands-architecture-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617224/25ccc461-5549-a36e-c1cb-97ff03c81447.png)
[出典：Islands Architecture: Jason Miller](https://jasonformat.com/islands-architecture/)

例えば、先ほどののコードでは、それぞれのコンポーネントが独立した島として機能し、ページ上で個別にロードされます。これにより、異なるフレームワークを使用しても問題なく動作します。

``` jsx
---
import Header from '../components/Header.jsx';
import Footer from '../components/Footer.vue';
import Sidebar from '../components/Sidebar.svelte';
import MarkdownContent from '../pages/index.md';
---

<Header />
<Sidebar />
<main>
  <MarkdownContent />
</main>
<Footer />

```

Astroではデフォルトでビルド時にJavaScriptが除去されますが、必要なJavaScriptを保持するためには、コンポーネントに`client:load`を適用します。

``` jsx
---
import Header from '../components/Header.jsx';
import Footer from '../components/Footer.vue';
import Sidebar from '../components/Sidebar.svelte';
import MarkdownContent from '../pages/index.md';
---

<Header client:load/>
<Sidebar client:load/>
<main>
  <MarkdownContent />
</main>
<Footer client:load/>

```

### 3. 高速な表示

Astroの最大の特長はその高速性です。Astroはさまざまなパフォーマンス向上のアプローチを採用しており、特に意識せずとも高速なWebサイトを構築できます。

Astro公式の一言には、次のようにあります：
> 私たちの目標は、Astroを使えば、遅いウェブサイトを作るのはほぼ不可能になることです。


ではなぜ高速なパフォーマンスが必要なのでしょうか？

Webサイトのパフォーマンスは、利益に直結する重要な要素です。
以下は、パフォーマンスと収益の関係を示すAstroの公式ドキュメントからの引用です：
> 高速化100msごと → コンバージョン数1％増（Mobify、年間38万ドルの収益）
50%高速化 → 売上12%増（AutoAnything）
20%高速化 → コンバージョン数10%アップ（Furniture Village）
40%高速化 → サインアップ15%増（Pinterest）
850ms高速化 → コンバージョン数7%増（COOK）
1秒遅くなるごと → ユーザー数が10%減少（BBC）

Astroが得意とする静的サイトでは、このようなパフォーマンスの優位性が特に重要です。

### 4. 拡張性
Astroは高い拡張性を持っています。好きなフレームワークでコンポーネントを書くことができ、100以上のインテグレーションを使用して拡張することが可能です。

https://astro.build/integrations/

そしてこれらの機能はすごく簡単に導入する事が出来ます。

例えば、Tailwindのインストールは次のコマンドだけです。
```
npx astro add tailwind
```

その後、いくつかの質問に`y`と答えるだけで、Tailwindの導入が完了します。

# Astroのはじめかた
Astroは誰でも簡単にを目指して開発をされています。
そのためプロジェクトを始めるのもとても簡単です。


### プロジェクトの作成

プロジェクトを作成するには、以下のコマンドを実行します。
公式サイトでは`npm`、`pnpm`、`yarn`のコマンドが紹介されていますが、`bun`でも作成できます。

今回は`npm`で進めていきます。
```
npm create astro@latest
```

コマンドを実行すると、プロジェクトの作成に関するいくつかの質問が表示されます。
```

 astro   Launch sequence initiated.

   dir   Where should we create your new project?
         ./AstroTest

  tmpl   How would you like to start your new project?
         Include sample files
 ██████  Template copying...

  deps   Install dependencies?
         Yes
 ██████  Installing dependencies with bun...

    ts   Do you plan to write TypeScript?
         Yes

   use   How strict should TypeScript be?
         Strict
 ██████  TypeScript customizing...

   git   Initialize a new git repository?
         Yes
 ██████  Git initializing...

  next   Liftoff confirmed. Explore your project!

         Enter your project directory using cd ./astroFast 
         Run bun run dev to start the dev server. CTRL+C to stop.
         Add frameworks like react or tailwind using astro add.

         Stuck? Join us at https://astro.build/chat

╭─────╮  Houston:
│ ◠ ◡ ◠  Good luck out there, astronaut! 🚀
╰─────╯

```

四角い謎の生物から「**Good luck out there, astronaut! 🚀**」と言われれば、Astroを始める準備は完了です。



### ローカルサーバーの起動方法
以下のコマンドを実行するとローカルサーバーが立ち上がります。
表示されたURLにアクセスすればページが表示されます。

```
npm run dev
```
今回の例ではhttp://localhost:4321/

```
 astro  v4.0.2 ready in 101 ms

┃ Local    http://localhost:4321/
┃ Network  use --host to expose
```


# 個人的に感じたAstroの良いところ

### 公式ドキュメントが充実している
ブログ作成のチュートリアルが用意されており、それだけで作成からデプロイまで可能です。チュートリアルにはチェックリストもあり、進行状況の把握が容易です。

ドキュメントは充実しており、公式で日本語に対応しているのが嬉しい点です。


### 学習コストが少なく簡単にWebサイトを構築出来る。

Reactの経験がある方には特に優しい設計ですが、HTMLとCSSの基本が分かれば、誰でも簡単に高速なWebサイトを構築できます。

### いろいろなフレームワークが使用出来る。
一つのサイトで複数のフレームワークを使用できるため、検索機能はReactで、サイドメニューはVueで作るなどごちゃごちゃ作るのが楽しいです。

同じ機能を別のフレームワークで作るのを簡単に試したり出来るのも良いところ。

# おわりに
ここまでお読みいただきありがとうございます。
Astroに興味を持っていただけたら、ぜひ公式ドキュメントから[チュートリアル](https://docs.astro.build/en/getting-started/)を始めてみてください。


# 参考
https://docs.astro.build/en/getting-started/

https://jasonformat.com/islands-architecture/