同じ構成のウェブサイトを一部の内容を書き換えて何回も作る必要があり、設定ファイルを元にサイトを生成するものをAstroで構築した。
ユースケース
今回Astroを使うことになったユースケースは以下の通り
- ほぼ同じ内容のサイトを一部のテキスト等を修正して何回も作る
- サイトのパスは一定ではないし、全く同じサイトの内容を異なるパスに何箇所かアップロードする
- JavaScriptを使った動的なコンテンツがあるが軽い内容
- 特に依存しているライブラリはない
- 生成するHTMLはすべて同じディレクトリに配置する
Astroの何が良かったか
フットプリントが軽い
完全に静的な内容だけであれば素のHTMLが吐き出されるだけなので、React系のものと比べると段違いに軽い。
Reactのインテグレーションを追加すると途端に重くなるのでPreactなども検討したが、今回は大した処理ではないし、既存の素のJavaScriptを流用して実装した。
React/Preactだとレンダリングのタイミングもちょっと遅い感じがしたのも一つの理由。
相対パスが使える
公式が対応しているわけではないが、astro-relative-link というインテグレーションを入れることにより、リソースのパスを相対パスに変更することができた。
やってることは静的ファイルが生成された後、その中に記載されてる href
や src
といったアトリビュートなどの内容を原始的に書き換えている感じで、構成によってはこれがうまく動かないこともある。今回のケースはこのインテグレーションでうまくいった。
尚、SSGのツールをいくつか調べたが、軒並みサイト全体の生成を対象にしており、リンクには絶対パスが使われることが基本。
AstroのGitHub Issueで相対パスへの対応を熱望する人達の声をいくつか見かけたが、ニーズとしてはニッチな方だし、パスの解決に複雑な問題を持ち込むことになるため対応は消極的なようだ。
わかりやすい
スタートガイドの以下のページを読めばサイトを作り始めることができると思う。
- https://docs.astro.build/ja/install-and-setup/
- https://docs.astro.build/ja/basics/project-structure/
- https://docs.astro.build/ja/develop-and-build/
設定周りを少しいじりたくなったら以下のページと、必要に応じて各APIリファレンスを読むような感じ。
- https://docs.astro.build/ja/guides/configuring-astro/
- https://docs.astro.build/ja/guides/typescript/
- https://docs.astro.build/ja/guides/environment-variables/
あとは Guides and recipes の項目のページ群も使う機能に絞って読んでおくと良い。
ドキュメントの日本語訳がけっこう進められていて、英語読むのに疲れたりしなくてありがたい。
拡張も容易
いろんなライブラリのインテグレーションも用意されているし、自分でビルド時のフックスクリプトを書くのも簡単。
Tips
いくつか今回のプロジェクトで役立ったことのメモ。
サイト全体で共有されるパラメータを設定する
ビルド開始時にサイトの設定ファイルを読み込み、それをミドルウェアで context.locals
に設定すると、各ページの Astro.locals
でその値を参照できた。
参考: https://docs.astro.build/ja/guides/middleware/
開発時とビルド時でインテグレーションを切り替える
astrobook というものを導入したのだけれど、これがビルド時に有効になっていると余分なファイルが出力されてしまう。
以下のようにしてビルド時に無効になるようにした。
integrations: [ import.meta.env.DEV ? astrobook({ directory: 'src', subpath: 'docs' }) : null ]
参考: https://docs.astro.build/ja/guides/environment-variables/
ビルドの際はnullがインテグレーションとして渡って無視される。この後ろにインテグレーションを書くと、このnullによって後続のインテグレーションが実行されなくなるので注意。
自分でインテグレーションを書く
簡単なものならば、astro.config.*
にインテグレーションをインラインで書いてしまえば良い。
クライアント実行のスクリプトにパラメータを入れる
Reactのインテグレーションを使っていたりするのだったら、アトリビュートとして渡せば良いのだが、素のJavaScriptだとそうもいかない。
そんな時は以下のように解決できる
--- import planData from '@/data/plans.json' --- <script set:html={`var plans = ${JSON.stringify(planData)};`}></script>