世界最速を謳う、話題のWebフレームワーク「Astro」を試してみた

## 概要
※ 本記事は **Astro の概要を把握・理解するための記事** です。「使い方」「書き方」といった技術的な記事は後で別記事にします。

普段、幅広く色々な技術で開発するため、色々な技術のドキュメントサイトを訪れることが多いのですが、最近「Astro」というワードを目にすることが増えました。

例えば、最近人気の [Tailwind CSS](https://tailwindcss.com/) やその辺りの技術系の公式ドキュメントで、「連携」部分の記載の中に、見慣れたフレームワークと並んでなぜか「Astro」という表記が含まれていることが多くあるのに気づきました。

調べてみたら、Astro は 2022 年 4 月にベータ版がリリースされた比較的新しい（記事執筆現在）技術で、たった一年で GitHub のスター数が約 30k にもなった非常に勢いがある技術で、今や大人気フレームワークの **Next.js** からも Astro に移行している人が結構いるみたいなので、初心者向けに情報をまとめてみました。

## Astro とは
**「Astro（アストロ）」** は、**"世界最速"** を謳うほどの超高速な画面読み込みと SEO に優れたページを作りやすい、Web フロントエンドのフルスタック・フレームワークです。

特に、**コンテンツ駆動型 Web サイト（Content-Driven Websites）**（＝ 要するに、記事やコンポーネント等の表示コンテンツが豊富なウェブサイト）を構築するのに適しています。

一言で表現すると **「豊富なコンテンツを速く表示すること」** に最適化された技術です。

近年、Next.js や Vue をはじめ、SPA（シングル・ページ・アプリケーション） を端に発する技術が非常に人気ですが、表示コンテンツ量が多くて、クライアントサイド（ユーザ端末側）で JavaScript も無駄にたくさん動いているため、Web サイトとしてのパフォーマンスや UX（ユーザ体験）が悪くなりやすいという課題をはらんでいます。

その課題に対して、技術的に解消するアプローチを重視して誕生したのが、この **"Astro"** のようです。

https://astro.build/

厳密には TypeScript でも書かれておりますが、JS（JavaScript）ベースの技術です。[GitHub](https://github.com/withastro/astro) で公開されており、[node パッケージ](https://www.npmjs.com/package/@astrojs/node) としても配布されています。

具体例として、以下の様なコンシューマ（一般消費者）向けの Web ページ・ユーザ体験の提供が、Astro の得意とする領域みたいです。

- ブログ
- コーポレートサイト
- ランディングページ（LP）を含むマーケティングサイト
- 出版サイト
- 仕様書やリファレンス等のドキュメントサイト
- ポートフォリオ
- コミュニティサイト
- E-コマースサイト 

ただし、「ユーザ認証」を厳密に管理しなければならないサービスは **不得意** な印象です。閲覧がメインのサイトには非常に良さそう👌

### 本当に速いの？ Next.js よりも？
どうやら一番速いという謳い文句みたいです。
![astro_hp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/cd984dcf-fd27-c656-dfb1-eadfff5dbe9c.png)


Chrome 拡張機能の **「Lighthouse」** を使って、SEO を含むサイトのパフォーマンスを見てみました。Astro の公式ページは Astro で作られているので、そちらを参考のため利用してみました。

![astro_hp_lh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/87207146-95c0-9c74-f8b0-95bffe568cda.png)

なんと、全部満点 💯。評価ページ内で花火が打ち上がってました。笑

## 特徴
- ウェブサイトを作成するのに必要なものがすべて組み込まれている **「フルスタック Web フレームワーク」**
- **とにかく表示が画面表示が速い（世界最速）**。それを実現する技術・設計方針が以下
  - **Astro Islands**（または、単に Islands）：Astro 開発チームが生み出した新しいアーキテクチャ
  - **Server-first（サーバ・ファースト）**：画面表示に関わる処理は、できる限り全てサーバ側でやる設計
  - **「JSゼロ」標準**：不要な JS（JavaScript）を自動的に排除する仕組み
- 豊富な連携・カスタマイズ可能性
  - 何百種類もの統合機能や API フックが用意されており、Tailwind、MDX など幅広い技術から選択・統合が可能
  - **UI-agnostic**（React、Preact、Svelte、Vue、Solid、Lit などの技術を１つのサイト内で組み合わせて使用できる技術設計）
- コンテンツ・コレクション
  - マークダウン形式コンテンツの整理、検証、TypeScript による型安全性の提供

要約すると、『ビルド後に HTML と CSS のみの状態にする静的ページ生成技術（厳密には、必要な JS だけ残す）』が最も特徴的で、
個人的には、この **「JS で書かれた、JS を排除する仕組み」** というのがとてもユニークだと思います。

### Astro Islands（Islands）
Astro は **「Islands（アイランド）」** という独自のアーキテクチャを開発・採用しています。

"Island" は英語で「島」を意味しますが、Astro においては、画面表示される部品（コンポーネント）の中で、インタラクティブなコンポーネントのことを指します。

より詳細な内容は [公式ドキュメント（英語）](https://docs.astro.build/en/concepts/islands/)をご覧ください。

主には、以下のポイントが特徴だと思います。

#### 不要な JS は取り除かれる
ビルド後に出来上がったページでは、不要な JS（JavaScript）は適宜取り除かれる仕組みなっているので、ランタイム用の JS 等は完全に削除されます（Zero JS, by default：「JSゼロ」標準）。

#### 完全に独立した部品として画面に表示できる
このアーキテクチャでは、サーバサイドで完全に生成するか、クライアントサイドで処理するかを、コンポーネント単位で完全に切り離すことができます。

```react:src/pages/index.astro
// サーバサイドでレンダリングする (デフォルト)
<MyReactComponent />

// コンポーネント単位で, クライアントサイドで実行する
<MyReactComponent client:load />
```
アーキテクチャとしての表記が "Islands"（複数形）で、実際に１つのコンポーネントを指す場合の表記が  **"Island"**（単数系）です。 

この Island １つ１つは、常にページ上の他の Island から分離して実行され、同一ページ上に複数の Island を存在させることができます
更に、 Island は、異なるコンポーネント・コンテキストで実行されていても、状態を共有し、互いに通信することができます。

この柔軟性により、Astro は React、Preact、Svelte、Vue、SolidJS といった **複数の異なる UI フレームワークを同一ページに混在させることもできることが可能** となっています。
例えば、「Vue から React に全体を変えるから、あのカレンダーコンポーネントは仕様・デザインが変わっちゃうね」みたいなことも、Astro なら「その部品だけそのまま流用」って選択もできる様になります（やらないとは思いますが）。

複数技術の混在って、むしろ遅くなりそうな気がするのですが、それでも速く表示できるってすごいですね！🙌✨

#### 遅延読み込みもできる
内部で [Intersection Observer API（交差オブザーバー API）](https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API) を利用しており、これを利用すれば指定した「コンポーネントがブラウザに見えるまで読み込まない」といった設定も可能で、これによってページの読み込み時間を減らすことも可能になっています。

## アプリ生成手順
実際に Astro で Web アプリを作る手順も紹介しておきます。

コンソールを開いて、以下のコマンドでプロジェクトを自動生成します。
```bash
npm create astro@latest
```

以下、実行結果（対話形式で選択肢に回答していきます。お好みに合わせて回答してください）
```bash
# 初めて Astro 使う場合のみ表示される
Need to install the following packages:
create-astro@4.7.2
Ok to proceed? (y)
  # 👉 そのままエンターキーで OK

# かわいいアニメーションが挨拶してくれる (Git 利用時は Git ユーザ名も表示)
 astro   Launch sequence initiated.

╭─────╮  Houston:
│ ◠ ◡ ◠  Welcome to  astro  v4.3.5, to3izo!
╰─────╯

╭─────╮  Houston:
│ ◠ ◡ ◠  Let’s build something great!
╰─────╯

# Q1. ディレクトリ名はどうする？ (デフォルト名はランダムに生成される)
   dir   Where should we create your new project?
         ./orbital-osiris
  # 👉 文字入力で名称を決められる
  # 👉 デフォルトでよければ、そのままエンターキーで OK

# Q2. テンプレートを利用してプロジェクトを作る？
  tmpl   How would you like to start your new project?
         ● Include sample files (recommended)
         ○ Use blog template 
         ○ Empty 
  # 👉 カーソルキーで選択してエンターキーで決定

# Q3. 言語は TypeScript で書く？
    ts   Do you plan to write TypeScript?
         ● Yes  ○ No 
  # 👉 カーソルキーで選択してエンターキーで決定

# Q4. ストリクトモード（厳格な構文ルール）にする？
   use   How strict should TypeScript be?
         ● Strict (recommended)
         ○ Strictest 
         ○ Relaxed 
  # 👉 カーソルキーで選択してエンターキーで決定

# Q5. 依存関係をインストールする？
  deps   Install dependencies? (recommended)
         ● Yes  ○ No 
  # 👉 カーソルキーで選択してエンターキーで決定

# Q6. Git を初期化する？
  git   Initialize a new git repository? (optional)
         ○ Yes  ● No 
  # 👉 カーソルキーで選択してエンターキーで決定

      ◼  Sounds good! You can always run git init manually.

# ファイル自動生成中
 ██████  Project initializing...
         ■ Template copied
         ■ TypeScript customized
         ▶ Dependencies installing with npm...

# 自動生成完了
      ✔  Project initialized!
         ■ Template copied
         ■ TypeScript customized
         ■ Dependencies installed

  next   Liftoff confirmed. Explore your project!

         Enter your project directory using cd ./orbital-osiris 
         Run npm 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! 🚀
╰─────╯
```
かわいいアイコンと共にプロジェクトの自動生成が完了します。
最初に訊かれるディレクトリ名は毎回ランダムな名前を提案されます（なぜか全て宇宙っぽい響きの名前）。

### 起動確認
では、早速アプリを起動してみましょう。
今回は「orbital-osiris」というディレクトリで生成したので、その前提で以下の手順を実施します。

```bash
# 生成したディレクトリ名に移動する
cd ./orbital-osiris

# アプリ起動
npm run dev
```

アプリ起動時の `npm run dev` は、内部では `astro dev` を実行しています。
この `astro dev` コマンドは、マシンの空いてるポートを勝手に探してくれ、そのポートで起動してくれる便利なすごいやつです。なので、２つの Astro アプリを同時に `npm run dev` で起動しても、プロセスが衝突することなく起動してくれます

起動コマンド実行後、以下の様になればアクセス可能です。
```bash
> orbital-osiris@0.0.1 dev
> astro dev

▶ Astro collects anonymous usage data.
  This information helps us improve Astro.
  Run "astro telemetry disable" to opt-out.
  https://astro.build/telemetry


 astro  v4.3.5 ready in 184 ms

# 起動完了. 以下の URL でブラウザから表示できる
┃ Local    http://localhost:4321/
┃ Network  use --host to expose

01:21:39 watching for file changes...
01:23:11 [200] / 13ms
```

表示された通り、Web ブラウザを開いて `http://localhost:4321` にアクセスしてみましょう。

![astro_demo_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/cbbd9b5e-0f18-2cd1-0d7b-0645597af7c0.png)

無事にページが表示できました。
ここから、表示にあるように `src` ディレクトリ配下を整備してオリジナルのサイトを構築していきます。

起動したサーバを停止するには、コンソールで **「control + C（CTRL + C）」** を実行すれば止まります。

## ブログテンプレートも試してみた
先ほどのアプリ自動生成時に、テンプレートについての選択肢で、デフォルトの `Include sample files (recommended)` を選択しましたが、ブログテンプレート用の `Use blog template` を選んでみたらどんな画面が生成されるのかも確認してみました。

### 生成された画面
トップページ
![astro_blog_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/14bf6da6-f1f4-f63f-f4f0-a1430104e69b.png)

About ページ
![astro_blog_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/fbef1dda-9691-5ccf-5529-e015931b5a14.png)

記事一覧ページ
![astro_blog_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/82e14d6f-59f9-8846-327c-8cb7f2520ba4.png)

記事詳細ページ
![astro_blog_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/0a1f14f1-d063-f539-68a6-e7b05b1bdd99.png)

上記の様な画面が自動生成され、ある程度勝手にブログサイトっぽいテンプレートにしてくれていました！
メニュータブの選択状態なども作ってくれています。ここからカスタマイズすると非常に楽そうで便利です✨

### シンタックス
画面の記法は、基本的にHTML とカスタムコンポーネントを組みあわせる様な、React っぽい書き方をします（後述）が、他にもマークダウン形式でよく見る記法も使えるみたいです。

画像表示
```md
![Alt text](./full/or/relative/path/of/image)
```

引用（バッククォート）
```md
> これは引用文です。
```

テーブル
```md
| Italics   | Bold     | Code   |
| --------- | -------- | ------ |
| _italics_ | **bold** | `code` |
```

リスト
```md
- List item
- Another item
- And another item
```

他にも、コードブロックなども使えます。

## VS Code 拡張機能
基本的に `.astro` 拡張子のファイルで開発をしていきます。

VScode（Visual Stuido Code）で開発する場合は、拡張機能も公式に用意されているので、開発作業時のシンタックス表示も問題ありません。

![astro_vscode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/5ad1b9f6-5091-7515-5967-a71cfff0a16d.png)

## 静的サイトジェネレータとして最強かもしれない
パフォーマンスが非常に高いのですが、そもそも「静的なページを生成すること」にもかなり特化しているため、Astro でビルドした成果物を配置するだけで、あらゆるサービスで Web サイトとしてデプロイできちゃいます。

静的サイトとしてを使うのであれば、AWS の S3 バケツや、GCP のバケット（＝ Firebase Hosting も同様）にだってデプロイして、Web サイトとして公開できちゃいます。

SSR にも対応するので、Vercel、AWS Flightcontrol、Deno などでも公開可能です。

## まとめ
### 所感
とりあえず、個人的には **"革新的"** だと思ってしまいました。単純にすごいと思います。
技術的にもユニークだし、開発具合も非常に活発であるために新しいフレームワークであることがメリットとして輝いていると思います。

ただし、万能技術ではないので、ドキュメント等みながらデメリットや不得意なこともきちんと把握し、静的コンテンツの道を行くのか、SSR の道を行くのかはきちんと方針を決めて分離した方が良さそうです。

あと、関係ないですが公式のキャラクターがかわいい

![astro_chara.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/a39d735e-295f-1f15-4ef5-ef495c8ef3ec.png)


### 技術記事
ファイル構成や、画面の開発方法に関する内容は、別記事にしていこうと思います。Astro が気になった方は、この機会のフォロー等いただけると幸いです 🙌✨