Astroを使ってみた所感など

:::note warn
(2023/09/25追記)
このページはAstroのv2.x.xを使用した際の感想です。v3ではいくつかの内容が変更されているので、参考程度にお願いします。
:::

ずっと気になっていた[Astro](https://astro.build/)を使ってみたので、それの所感をまとめておきたいと思います。筆者はReactが好きなので、その目線での所感になっていることはご了承ください。

# Astroとは
https://astro.build/

Astroはパフォーマンスを重視した静的サイトジェネレーターです。
ページベースのルーティングを採用しており、基本的に*.astroファイルを使ってサイトを構築していきます。

# Astroのメリット
## パフォーマンスがよい
パフォーマンス重視でJavaScriptのコードがビルドされた静的サイトに入らないだけあって、普通に作れば本当にパフォーマンスのいいサイトができます。
もちろん、パフォーマンスは落ちることもあるでしょうが、筆者が普通にサイトを構築した限りでは、[PageSpeed Insights](https://pagespeed.web.dev/?hl=ja)も、パフォーマンス上の配慮を特にすることなく満点でした。

## TypeScriptを標準サポート
TypeScriptを標準でサポートしているので、型チェックが効きます。JSなしを推しているのに、TypeScriptの標準サポートは心強いです。

## インテグレーションが豊富
インテグレーションとよばれる、プラグインのようなものが、かなり豊富です。

### UIライブラリのサポート
例えば、[@astrojs/react](https://docs.astro.build/en/guides/integrations-guide/react/) というインテグレーションを追加することにより、一枚のWebページの一部にReactコンポーネントをいれることができます。
これはVueやSvelteなどもサポートされており、一枚のページに複数のUIライブラリ/フレームワークを混在させることも可能です。

しかも、これらのUIフレームワークによって書かれたコンポーネントは、動的な要素がない場合には、ブラウザでhydrationを行いません。DOM生成のために使われるというのは、Next.jsのapp routesのサーバーコンポーネントに似ていますね。

:::note info
もちろん、Reactのフックを使用しているなど、動的な要素がある場合には、hydrationが必要になりますが、`client:`から始まる属性を付与することで、hydrationされるタイミングまで制御できます。
たとえば、`client:load`でページロード時、`client:visible`でコンポーネントがビューポートに入った時にhydrationできるなどです。→[参照](https://docs.astro.build/ja/reference/directives-reference/#client-directives)
:::

### SSRのサポート
Astroは基本的にSSG(静的サイト生成)をしますが、必要に応じて、SSR(サーバーサイドレンダリング)も可能です。Cloudflare WorkersなどのエッジでのSSRにも対応しているのはかなり魅力です。

### パフォーマンス改善
パフォーマンス改善に役立つインテグレーションが豊富です。パフォーマンスを重視するコミュニティなためか、ほかではあまり見られないようなインテグレーションがすでにあります。
何個かすごいと思ったものを挙げておきます。

#### [@astrojs/image](https://docs.astro.build/en/guides/integrations-guide/image/)
公式のインテグレーションです。画像の最適化をビルド時に行えます。画像を`import`して、属性として画像のサイズやフォーマットなどを指定すると、ビルド時にもとの画像から生成してくれます。リモートの画像にも対応しているのは地味に便利です。
Next.jsの`next/image`のようなものが、すぐに使えるのは、かなり便利です。

:::note info
ただし、ぼかしをいれるなどの処理には対応していないようです。
:::

:::note warn
(2023/09/25追記)
Astro v3では@astro/imageは削除され、astro本体により提供されるようになりました。また、@astro/imageではPictureコンポーネントがありましたが、pictureコンポーネントは削除されました。
:::

#### [astro-compress](https://github.com/astro-community/astro-compress)
画像やスクリプト、HTMLなど、すべてのアセットを、ビルド時に圧縮して容量を小さくしてくれるやつです。標準ではHTMLなどがminifyされていないので、入れておいた方がいいと思います。

#### [astro-google-fonts-optimizer](https://github.com/sebholstein/astro-google-fonts-optimizer)
[Next.jsが標準でやるGoogleフォントの最適化](https://nextjs.org/blog/next-10-2#automatic-webfont-optimization)をやってくれるやつです。

#### [astro-critters](https://github.com/astro-community/astro-critters#readme)
クリティカルCSSと呼ばれる、ロードされて一番最初にビューポートで見える部分のCSS1をインライン化することで、FCPやLCPなどの改善が望めます。
[critters](https://github.com/GoogleChromeLabs/critters)のAstro用のインテグレーションなのですが、これがコミュニティによって維持されているのは、個人的にはかなりポイントが高かったです。

他にも、多くのインテグレーションがあるので、いろいろ調べてみることをお勧めします。

## CSSのスコープが標準機能
*.astroファイルは、直接`<style>...</style`を使ってコンポーネントにスタイルを付加できるようになっているのですが、このスタイルは、明示的に指定しない限り、デフォルトでは、そのコンポーネント内の要素にしか適用されないようになっています。
`<slot />`(Reactでいうchildren)で外部から注入される要素に対しても適用されません。
なので、そのコンポーネントのスタイルを、ほかへの影響を気にせず書けるようになっています。

## ドキュメントの大部分が日本語
英語が読めれば問題ないのですが、完全ではないものの大部分が日本語に翻訳されているので、日本語のほうが読みやすいというひとにとっては、かなり使いやすいのではないでしょうか。

# Astroのデメリット
以下は、Astroを使ってみて感じた、欠点です。

:::note warn
もしかしたら、見落としている部分もあるかもしれないので、「それできるよ～」とかがあったらぜひ教えてください。
:::

### エディタ補完が弱い
Visual Studio Codeを使用しましたが、拡張機能をいれても、Next.jsを使っているときと同じような補完は得られないことが多かったです。なので、快適な開発経験が欲しい人にはあまり向いていないかもしれません。
HTMLタグの補完が弱かったり、CSSのプロパティの補完が弱かったりしました。
また、なぜかHTMLエンティティのシンタックスハイライトが青くならないのが地味に不便でした。
もちろんこの辺は、今後改善されていくことを期待したいと思います。

### ピュアなJavaScript/TypeScriptではない
*.astroという独自のファイルを使用していることもあり、Reactのような、ピュアなJavaScript/JSX/TypeScript/TSXではありません。
また、Propsの型定義をするときには、ファイルの先頭に`Props`という`interface`を定義するのですが、これが`Astro.props`の型になるのがどうしても気持ち悪いと感じてしまいました。(まあ慣れればOKですが。)

### 出力がES Modulesになる
Astroは、基本的にビルドされたサイトにスクリプトを挿入しませんが、挿入したいJavaScriptがあった場合には、もちろん挿入することができます。
しかし、JavaScriptファイルがES Modulesの`import`を使うようになっており、ひとつのファイルにバンドルされません。
私のサイトの場合、以下のようなほとんど内容のないファイルを、外部スクリプトから`import`で読み込んでおり、無駄なリクエストがされているのをなんとかできないかと思っています。
```js
const s="_a_39d1c_1",a={a:s};export{a as s};
```
やはり、リクエストチェーンはできるだけ避けたいものです。

### CSSのスコープ化に`:where`を使用している
CSSのスコープ化には、`:where`を使用しています。`:where`は、2023年6月末の時点で、みなさんおなじみの[Can I useで確認](https://caniuse.com/mdn-css_selectors_where)してみると、Globalが92.82%となっており、まだ使用を躊躇する場面もあるのではないでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645823/c5508db4-3bb4-1203-5096-b96c230dabae.png)

CSSの`:where`のほかにも、`Web components`など、新機能も多用しているので、より広いブラウザでのサポートをしたい場合には向いていないかもしれません。

:::note warn
(2023/09/25追記)
Astro v3では、:whereによるスコープ化以外に、data-*属性を使ったスコープ化を設定で選べるようになったのでこの問題は大方解決したと思われます。
:::

### CSS in JSの多くは未対応
TailwindCSSは公式でサポートがありますが、`styled-jsx`や`emotion`などの多くのCSS in JSライブラリはまだサポートされていません。
詳細については[こちらのissue](https://github.com/withastro/astro/issues/4432)でサポート状況や議論などが確認できます。

# 総合的な感想
静的なサイトを作りたくて、でも、素のHTMLやJSを書くならば、何か便利なフレームワークを使いたい、という場合にはかなり優れた選択肢になるかもしれません。
特に、パフォーマンスがいいことは事実です。また、中核の思想は、Next.js v13のapp routesに似ていると思います。
ただし、比較的新しめの機能も多用されており、古いブラウザのサポートが重要な時には、あまりいい選択肢とはならないかもしれません。
何かのお役に立てば幸いです。