Astro で限りなく内容が似ている複数のウェブサイトを作るには
「限りなく内容が似ている複数のウェブサイト」というものを生成したいときがある。例えば、以下のようなシチュエーションだ。
- 複数の EC サイトのサーバースペースに置く静的な HTML を作りたい (けど、リンク先などが完璧に同じではない)
- ページを、AB テストなどのために複数の場所に配置したい
静的サイトジェネレーターの側面を持つ Web フレームワークの Astro で、これが実現できるかどうか試してみよう。
環境変数を読み取って、Vite の定数をセットしてみる
Astro は Node.js 上で動いているので、process.env
から環境変数を取得することができる。
// @ts-check
import { defineConfig } from 'astro/config';
const param = process.env.PARAM ?? 'default';
const setting = {
'foo': {
name: 'foo foo',
url: 'https://aioilight.space/'
},
'bar': {
name: 'bar bar',
url: 'https://wangel.aioilight.space/'
}
}[param] || {
name: 'default default',
url: 'https://example.com'
};
export default defineConfig({
outDir: './dist/' + param,
vite: {
define: {
'__SETTING__': setting
}
}
});
astro.config.mjs で process.env
から環境変数を取得し、環境変数で可変させたい設定のオブジェクトを生成する。今回は環境変数 PARAM
があると想定する。PARAM
の値は process.env.PARAM
に入っている。環境変数が設定されていなかったときのために、デフォルト値 'default'
を用意しておく。変数 setting
に設定を意味するオブジェクトを代入する。用意されていない値が来たときは、 undefined
になるので OR 演算子でデフォルトのオブジェクトを代入させる。
Astro は Vite を使っている。defineConfig()
から、Vite の設定も変えることができる。Vite には define
という設定があり、ここでグローバル定数を設定することができる。vite.define
にそのままオブジェクトを突っ込む。
/// <reference path="../.astro/types.d.ts" />
declare const __SETTING__: {
name: string,
url: string
}
このままではこのグローバル定数への型情報は失われてしまっているので、Astro のファイルで型推論を効かすために、env.d.ts
で型を定義しておく。
---
const { name, url } = __SETTING__;
---
<body>
<h1>{name}</h1>
<p>{url}</p>
</body>
Astro のファイルでグローバル定数を使うときは、こんな感じ。
astro.config.mjs のほうで outDir
とか site
とかも可変させれば、今回の課題はクリアできる。
すべてをビルドする npm scripts
{
"scripts": {
"allbuild": "for %S in (foo bar) do @set PARAM=%S & npm run build"
}
}
このような npm scripts を作ると全部一気にビルドできる。これは Windows での場合で、環境変数をセットする都合上シェルによって構文が異なる。Windows 11 でも PowerShell ではなく cmd が使われるので VSCode 上のターミナルとも構文が異なる可能性がある。
こんな感じ。