Astro で1つのコードベースから複数のサイトを生成する
Astro で複数のサイトを生成していると、コンテンツは異なるがコードはほとんど同じということがある。そのような状況で、コードベースを一本化してメンテナンスを楽にする方法を検討した。
公式に案内されているものがあればそれを採用したかったのだが、見つけられなかったので、あまり凝ったことはせずに、シンプルにシンボリックリンクを使った方法で実現してみた。
サイトの構成
以下のようなディレクトリ構造にして、content のシンボリックリンクが示す先を切り替えることで、生成するサイトを切り替える。
.├── sites/│ ├── site-a/ # サイトAのコンテンツ│ │ ├── blog/│ │ ├── public/│ │ └── metadata.json│ └── site-b/ # サイトBのコンテンツ│ ├── blog/│ ├── public/│ └── metadata.json├── content -> sites/site-a/ # シンボリックリンク└── src/ # 共通コードpackage.json にサイト切り替えコマンドを用意している。
{ "scripts": { "switch:site-a": "ln -sfn sites/site-a content", "switch:site-b": "ln -sfn sites/site-b content" }}ビルド前にこのコマンドを実行することで、ビルド対象を切り替える。
pnpm run switch:site-apnpm run buildAstro 側は、content 以下を参照してビルドするように普通に設定している。サイトごとに挙動を変えたい場合は、設定ファイルも content 以下に配置して読み込めばよい。
ビルド・デプロイ
GitHub Actions の matrix 機能を使い、各サイトを並列にビルド・デプロイしている。自分の場合だと Cloudflare Workers をデプロイ先にしているので、wrangler.toml にサイトごとの環境を定義しておいて、デプロイ時に指定している。
get-sites: runs-on: ubuntu-latest outputs: sites: ${{ steps.set-matrix.outputs.sites }} steps: - uses: actions/checkout@v6 - id: set-matrix run: | SITES=$(ls -1 sites | jq -R -s -c 'split("\n")[:-1]') echo "sites=$SITES" >> "$GITHUB_OUTPUT"
deploy: needs: get-sites strategy: matrix: site: ${{ fromJson(needs.get-sites.outputs.sites) }} runs-on: ubuntu-latest steps: # ...
- run: pnpm run "switch:$SITE" env: SITE: ${{ matrix.site }}
- run: pnpm run build
- run: wrangler deploy --env "$SITE" env: CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} SITE: ${{ matrix.site }}[env.site-a]name = "site-a"
[env.site-b]name = "site-b"