Astroの特徴
コンテンツ管理を目的とするサービスと相性がいいアーキテクチャ
コンテンツ中心のWebサイト(ブログ、HP、ドキュメント)。特に初回のページロードのパフォーマンスが重要とされるサービス。Astroを使用してSSGしておけば、light houseで容易に90点以上のスコアを叩き出せる
アイランドアーキテクチャ
必要な時に必要なjavascriptしかブラウザに送信しないという考え方。近年の傾向として、大量のjsをブラウザへの配信を行うことで高速なページ表示の妨げになっているが、
Astroでは、サーバー側でhtmlレンダリングを完結させるため、これらのボトルネックが生じにくくなっている。基本的には、静的な1つのページ(島)の上にインタラクティブなjavascriptが必要な箇所が部分的に存在しているというイメージ
※公式ドキュメントより引用
クライアントサイドで実行したいjsは、Astroコンポーネント内の<script>タグに記載するか、コンポーネントにclientディレクティブを指定することで簡単に実現可能
ルーティング
MPAベース、従来のaタグで画面を遷移する。サーバーサイドからブラウザに返却するのはjsonではなく、Htmlファイル。jsによる画面遷移ではない(jsによる画面遷移をすると、その分ブラウザに送信するjsが必要なため、Astroの設計思想から外れる)
パスベースのルーティングとなっており、src/pages以下のファイル、例えば.astroファイルやmarkdownファイルなどがパスになる(そのままurlになる)
ページレンダリング
Astroは静的サイトジェネレータ。デフォルトSSGで設定変更によりSSRも可能。サーバーサイドでビルド時に全てのurlに応じたhtmlを生成する。動的ルートが必要なページは、getStaticPathsで定義する
なお、ページネーションが必要な場合はgetStaticPathsにpagenateを実装することで、簡単にページネーションのデータを生成できる
<実装例>
export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
const res = await getBlogs();
const posts = res.contents;
return paginate(posts, {
pageSize: 10,
});
}
動的なパラメーターを含むページネーションの生成も可能
https://docs.astro.build/en/core-concepts/routing/#nested-pagination
コンポーネント指向
react、vue、svelteなど主要な UIフレームワークに対応しており、どれか1つ、または複数のフレームワークを混在させることも可能。また、Astroには組み込みのastroコンポーネント(.astro)が存在するので、主要な UIフレームワークを使用せずともコンポーネント指向で開発可能。基本的にjsxと同じ感覚で記述できる
Astroコンポーネントの特徴
script部分
- Frontmatter(コードフェンスで囲われた部分)。js、tsを記述できる。定義した変数などはデフォルトではビルド時のみ実行される(ブラウザでは実行されない)
- トップレベルawaitが使用できるので、簡潔に非同期処理を記述できる
- 定義した変数をhtml部分で使用するには、ブレース({})を使用する。ブレース内にはjs、tsを書ける
html部分
- jsxのような記法で書くことができるプレーンhtml
- フロントマターの変数をクライアントサイドに渡す方法
define:vars={...}
サーバー側変数をコンポーネント フロントマターからクライアント<script>
または<style>
タグに渡すことができる
---
const message = "hoge";
---
<script define:vars={{ message }}>
console.log(message);
</script>
他のフレームワークなどでも用意されているLayoutコンポーネントも実装可能。共通ヘッダーやフッターなどは、Layoutコンポーネントで共通化するように設計されており、vueと同様、slotを使用して子要素を差し込むことが可能
propsもreactやvueなどと同様にコンポーネントに渡すことが可能。Astro.propsという特殊なオブジェクトがあるので、そちらを使用する。子コンポーネント側でprops型をinrterfaceで指定すると、親で漏れているプロパティがあれば、エディターでコンパイルエラーを出せる
コンテンツの管理方法
ブログ記事などのコンテンツの管理方法は大きく2つ
- headless cmsを使用しそこから取得する
- markdownでsrc/content以下に配置し、それを表示する
このやり方だと、astro2.0からのCollection apiを使用して記事の取得やソート、フィルターが容易に行うことができるようになっている
なお、Astroは後者のローカルのマークダウンを使用する方法をベースとして設計しているらしい
https://docs.astro.build/en/guides/markdown-content/#fetching-remote-markdown
スタイリング
tailwind、scssなど主要なcssに対応。インラインスタイル(style属性)も可能。astroコンポーネント内にstyleタグを記述することが可能。(VueのSFCのような感覚)
---
---
<div class:list={['box', { red: isRed }]}><slot /></div>
<style>
.box { border: 1px solid blue; }
.red { border-color: red; }
</style>
<script>
<script/>
スコープ指定可能(デフォルトはローカルスコープなので、styleタグにis:globalディレクティブを指定すると、グローバルになる)。もちろん、global.cssとして定義し、別途importすることも可能
define:vars:ディレクティブを使用すると、Frontmatter内で宣言した変数をstyleタグ内で使用できる
---
const backgroundColor = "rgb(24 121 71)";
---
<style define:vars={{ backgroundColor }}>
h1 {
background-color: var(--backgroundColor);
}
</style>
インラインでclass:listディレクトブを使用すると、複数のクラスを配列でマージできる
<span class:list={[ 'hello goodbye', { world: true }, [ 'friend' ] ]} />
Markdownから生成されたHTMLにTailwind CSSのスタイルを適用する方法
参考:https://uki00a.github.io/blog/articles/006-use-tailwindcss-with-astro/
フォント
googleフォントを使用したいことが多々あると思う。こちらの公式ドキュメントのやり方で簡単に使用することが可能
https://docs.astro.build/ja/guides/fonts/#fontsource%E3%82%92%E4%BD%BF%E3%81%86
テーマ
デザインを一から作らなくても、WordPressなどの他CMSと同様、テーマが存在する(有償・無償どちらもある)
インテグレーション
わずか数行のコードでプロジェクトに新しい機能や挙動を追加できる。例えばVueやReactのようなUIフレームワーク、tailwindのようなスタイリングフレームワーク、画像最適化のための@astro/images、サイトマップ生成の@astro/sitemapなどのように、サイト制作で使用するであろう機能は基本的に一通り用意されている。(スクラッチで作成する必要がない)
tailwind
外部のサービスやツールはインテグレーションという形で定義されており、例えばtailwindなら以下のように追加できる
npx astro add tailwind
あとはastro.config.mjsに以下のように追加するだけ
import sitemap from "@astrojs/sitemap";
// https://astro.build/config
export default defineConfig({
site: SITE_DOMAIN,
integrations: [
tailwind(), //here
],
});
画像最適化
@astro/imagesをインテグレーションが用意されている。
npx astro add image
また、幅・高さ・アスペクト比を指定でき、軽量なavifなど特定の出力フォーマットに画像を変換できる
サイトマップ
こちらを使用すると、http://localhost:3000/sitemap-index.xml
とhttp://localhost:3001/sitemap-0.xml
が生成される。(1 つ目は 2 つ目のインデックスにリンクするだけのファイル)この 2 つのページに投稿などの動的ページが含まれている。
ビルド時に /distディレクトリに生成される
サードパーティスクリプトの読み込み
普通にGoogle AnalyticsやAdsenseをheadタグなどに設置すると、PageSpeed Insightsのパフォーマンスが下がる。AstroではPartytownというインテグレーションがありscriptをメインスレッドとは別にロードできるようにすることができ、パフォーマンスの低下を防止可能
npx astro add partytown
WordPressからの移行
Wordpressのコンテンツをxmlとして出力し、npmパッケージのツールを使用してmdに変換することが可能なツールがある。Wordpressからの移行をしたいが、コンテンツの移行に困っているという方はぜひ。
ビルド周り
viteを使用して高速にビルドしているので、開発がサクサク進む
型セーフ
デフォルトでtypescriptに対応しているので、開発体験が良い
VSCode拡張
※拡張機能のインストール推奨(オートコンプリートなどが効くようになる
https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode
テスト
単体/結合テストであれば、vietest、e2eであればPlaywrightが組み込むことが可能。専用のドキュメントも用意されており、こちらの手順に従えば実現できる。
留意点
向き不向きを理解する
公式ドキュメントでも言及されていること。複雑な状態管理などが必要なサービスには適していないが、コンテンツ管理向けのブログ、ウェブサイト、ECなどと相性が抜群。間違っても頻繁にデータの更新など動的な処理が必要な複雑なアプリケーションの開発には選定しないように。
モダンフレームワークを使用せずに完結できるか
ReactやVueなどのモダンフレームワークを使用せずにastroコンポーネントだけで完結するのは少し厳しそう。理由は、Astroコンポーネントでは、命令的に<script>タグの中にDOM操作をゴリゴリ記述する必要があるため(宣言的に書けない)
いくら、静的なWEBサイト等とはいえ、保守性を考慮すると宣言的に書いておきたい。
独自ドメイン
カスタムドメインの場合は、astro.config.mjsのsiteも合わせて更新すること。しないと"og:url
に正しく反映されないので注意
ハマった点
自分自身が技術ブログを開発して、苦戦して点。
コードのシンタックスハイライト
Astroでは、ShikiとPrismをビルトインでサポートしており、コードのシンタックスハイライトが可能になっている。
https://docs.astro.build/en/guides/markdown-content/#syntax-highlighting
ただし、これはMarkdownまたはMDXファイルを対象としているため、リモートからコンテンツをフェッチ(microcmsなどのヘッドレスCMS)する方式だと、対象外となる。そのため、自分自身でマークダウンをパースする際に一手間加える必要がある。
参考:https://codeseterpie.com/blog/f31prr55i/
まとめ
いかがでしたでしょうか。本記事では、Astroの特徴やシステムを開発する際のポイント/TIPSを紹介しています。HeadlessCMS&Astro環境なら高速なサイトを簡単に作れるし、コストもかからない。向き不向きはあるものの、しっかり理解して使用すれば簡単に高パフォーマンスなサイトを構築できるので、ぜひ参考にしてみてください。