Astroで静的サイトを構築してみて

公開日:2023/2/1更新日:2023/2/2

先日、Astro静的サイトを構築しました。Astroに触れたのはこのプロジェクトが初めてで、フレームワークの順番としては、Nuxt.js、Next.js、Gatsby.jsに続いて4つ目です。

まず、結論から言うと、静的サイト構築ならAstro一択と思うほど完璧なフレームワークです。

軽量で超高速なサイトが簡単に構築できる

Astroの最大の魅力はビルド後のファイルにあります。

今や、静的サイト構築(SSG)はどのフレームワークを選んでも実現できますが、Astroのアプローチは他のフレームワークと一線を画していて、可能な限りサーバーサイドで処理を実行してHTMLファイルを生成するため、軽量で超高速通信が可能なサイトを構築してくれます。

他のフレームワークだと、バンドルサイズを削るために試行錯誤する必要がありますが、Astroでは不要です。

例として、以下はPageSpeed Insightsでブログページ(画像あり、アドセンスなし)を計測したモバイルとPCの結果ですが、何も気にせずにサイトを構築しただけで満点に近いスコアが獲得できています。

PageSpeed Insightsの一例(モバイル)
PageSpeed Insightsの一例(PC)

SPAの必要性とは?

Astroのサイトが速い背景に、SPAではなくMPAのシステムを採用していることもあります。

Next.js、Nuxt.js、Gatsby.js、主要なフレームワークはどれも、次のページへリロードなしで遷移する機能があり、プリフェッチや、不要な通信をしないことで高速読み込みができることを1つのウリにしていますが、Astroには同様の機能がありません。つまり、HTMLファイルを1から読み込みます。

SPAとMPAのアプローチにはそれぞれメリットとデメリットがありますが、ほとんどのサイトではMPAこそベストなのではないかと気づかされました。

なぜなら、大規模アプリケーションではない普通のブログやコーポレートサイトでは、1ページ目で離脱するユーザーが大半だからです。

私自身、リロードせずにページ遷移できることにスマートな印象を抱いていたのですが、自己満足だったのだと、今では思います。

学習難易度の低さ

Astroでは基本的に.astroファイルを使い、ReactやVue同様に書き方のルールがあるのですが、HTMLとReactとVueのそれぞれの良さを混ぜたような記述方法になっていて、すぐに慣れました。

以下、サンプルコードです。

---
import TheFooter from "./TheFooter.astro";

const title = "Hello Astro!";
const nav = [
  { label: "menu1", href: "/menu1" },
  { label: "menu2", href: "/menu2" },
];
---

<div>
  <h1>{title}</h1>
  <div>{nav.map(({ label, href }) => <a href={href}>{label}</a>)}</div>
  <TheFooter />
</div>

<style>
  h1 {
    color: red;
  }
</style>

一点、AstroはReactライクな書き方なのですが、onClickでの直感的な記述ができず、素のJavaScriptで記述する必要があります。

<!-- これは動かない -->
<button
  onClick={() => {
    console.log("クリックされました!");
  }}>クリックする</button
>

<!-- これは動く -->
<button id="button">クリックする</button>
<script is:inline>
  document.getElementById("button").addEventListener("click", () => {
    console.log("クリックされました!");
  });
</script>

jQueryやReactやVueの登場で、今や素のJavaScriptを書く機会は以前より明らかに減ったため、苦手意識を持っている方もいると思いますが、AstroはReactやVueのファイルが混在可能なので、コンポーネント単位で切り分けることで対処可能です。

例として、私の今回のプロジェクトでは、モーダル部分をReactで構築したのですが、モーダルの開く・閉じるの状態管理にuseState()を使っています。

そして、呼び出す側(親)ではclient:only="react"の引数を与え、Reactコンポーネントであることを明示的に伝えています。

---
import { MyReactComponent } from "./anywhere";
---

<div>
  <MyReactComponent client:only="react" />
</div>

こうして他のフレームワークを混在させても、最終的にはAstroがよしなにやってくれるので、これもAstroの大きな強みだと思っています。

優れた開発体験

デフォルトでTypeScriptに対応しているのはもちろん、モジュールの追加の際に自動で設定ファイルが更新されたり、公式のドキュメントが充実しているなど、至れり尽くせりです。

また、Astro自体は強力な静的サイトジェネレーターですが、他のフレームワーク同様ホットリロードがあるため、サクサクと開発できます。

その他、モジュールライクな機能も提供されており、@astrojs/partytown@astrojs/tailwind@astrojs/imageなどを使いましたが、良くできていて(変なエラーなどもなく)、Astroコミュニティーの強さも実感しました。

※ちなみにsitemapは自作しています。

同時にNuxt3のプロジェクトの開発を進めていたのですが、スピード感が非常に遅く、最終的には静的サイト用の画像生成を自分でやったくらいなので、コミュニティーの盛り上がりや関わる人の多さなどもフレームワークの選定に欠かせない要因だと、今回しみじみ思いました。

まとめ

目的や開発環境(チーム)によって、フレームワークの選定基準は変わってくると思いますが、速いサイトを構築できること、他のフレームワークと共存できることを考慮すると、Astroの活躍の場面はもっと増えるのかなと思います。