ビルドとデプロイ
dist/ の中身と vantage-manifest.json。同一オリジン配信と、フロント/サーバーを別オリジンに分けるデプロイ(S3+CloudFront ⇄ Lambda など)。
vantage build は本番用の成果物を dist/ に出力します。ここから先の配信方法は 2 つに大別できます。
サーバーとフロントを同一オリジンでまとめて出すか、フロントを静的ホスティング(S3+CloudFront /
Cloudflare Pages)に、サーバーを別オリジン(Lambda / コンテナ)に分けて出すかです。分離構成の
ために Vantage は「API ベースURLの切り替え」と「CORS」を用意しています。
ビルド出力
vantage build # → dist/
dist/
├── client/ クライアント(index.html + ハッシュ付きアセット、ルートごとに分割)
├── server/index.mjs server/ がある場合のみ(esbuild / node20 / ESM バンドル)
└── vantage-manifest.json デプロイ契約
vantage-manifest.json が配信側との唯一の契約です。フィールドは次の通り。
| フィールド | 内容 |
|---|---|
schemaVersion |
マニフェストのスキーマ版(現在 1) |
mode |
"spa"(client のみ)/ "fullstack"(server あり)。server/ の有無から導出 |
client |
クライアント成果物への相対パス("./client") |
server |
サーバーバンドルへの相対パス("./server/index.mjs")。fullstack のみ |
spaFallback |
SPA フォールバック用 HTML("./client/index.html") |
runtime |
サーバーの実行環境("node") |
preview でローカル確認
デプロイ前に、本番ビルドをローカルで動かして確認します。
vantage preview
vantage preview は vantage-manifest.json の mode を読み、fullstack なら Node サーバーを
起動(既定 :4173)、spa なら静的プレビューを立ち上げます。
デプロイの 2 つの形
同一オリジンにまとめる
Node プロセス 1 つで client と /api の両方を配信。設定が最小で、CORS も不要。
フロントとサーバーを分ける
フロントを S3+CloudFront 等へ、サーバーを Lambda / コンテナへ。API ベースURLの切り替えと CORS が必要。
同一オリジンにまとめてデプロイ
最も単純な形です。dist/ をまるごと Node が動く環境(コンテナ / VM)に置き、生成された
サーバーを起動します。同一プロセスが静的アセットと /api/* の両方を捌くため、API ベースURLの
切り替えも CORS も不要です。
# dist/ を配置したサーバー上で
PORT=8080 node dist/server/index.mjs
サーバーはポート PORT(未指定なら 3000)で待ち受けます。クライアントは相対パス
/api/... をそのまま同一オリジンで呼びます。
フロントとサーバーを分ける(S3+CloudFront ⇄ Lambda)
フロントを CDN の静的ホスティングに、サーバーを別オリジンに置く構成です。よくある組み合わせは
「dist/client を S3+CloudFront、dist/server/index.mjs を Lambda / コンテナ」です。別オリジンに
なるため、次の 2 点が必要になります。
1. API ベースURLを切り替える
クライアントの API 呼び出しは、@squadbase/vantage/query の apiFetch / apiUrl を通します。
これが /api を呼ぶ唯一の継ぎ目で、ベースURLをここで差し替えられます。
import { apiFetch, useQuery } from "@squadbase/vantage/query";
useQuery({
queryKey: ["monthly-analysis"],
// パスは server/api の綴りのまま(/api を含める)
queryFn: () => apiFetch("/api/monthly-analysis").then((r) => r.json()),
});
ベースURLは PUBLIC_API_BASE_URL から読みます。未設定なら空で、従来どおり同一オリジンの
相対パス(/api/monthly-analysis)になります。設定すると、その値が前置されます
(https://api.example.com/api/monthly-analysis)。切り替え方法は 2 つ。
(a) 環境変数で上書き — .env や CI の環境変数に置きます。PUBLIC_ 接頭辞なので、
そのままクライアントバンドルに焼き込まれます。
# .env(またはCIの環境変数)
PUBLIC_API_BASE_URL=https://api.example.com
(b) ビルド時にフラグで指定 — vantage build に --api-base-url を渡します。
vantage build --api-base-url https://api.example.com
2. CORS を許可する
フロントとサーバーが別オリジンになると、ブラウザは CORS を要求します。サーバー側で
CORS_ORIGIN を設定すると、/api に CORS(プリフライトの OPTIONS 応答を含む)が付きます。
未設定なら CORS は無効で、同一オリジン運用はそのままです。
# サーバー(Lambda / コンテナ)の環境変数
CORS_ORIGIN=https://app.example.com # 単一オリジン
# CORS_ORIGIN=https://a.example.com,https://b.example.com # カンマ区切りで複数
# CORS_ORIGIN=* # すべて許可(credentials とは併用不可)
CORS_CREDENTIALS=true # Cookie / 認証情報を許可する場合のみ
| 変数 | 役割 |
|---|---|
CORS_ORIGIN |
許可するオリジン。* / 単一 / カンマ区切りの複数。未設定なら CORS 無効 |
CORS_CREDENTIALS |
true のとき資格情報(Cookie 等)を許可。* とは併用しない |
許可メソッドは Vantage の API が使える GET,POST,PUT,PATCH,DELETE,OPTIONS が自動で設定されます。
この挙動は dev サーバーと本番 Node サーバーで共通なので、開発中に CORS を確認できます。
3. フロントを静的ホスティングに置く
dist/client/ を S3(+ CloudFront)や Cloudflare Pages にアップロードします。SPA なので、
未知パスは spaFallback(index.html)に返す必要があります。
- S3 + CloudFront: CloudFront の「カスタムエラーレスポンス」で
403/404を/index.html(ステータス200)に書き換えます。 - S3 静的ウェブサイトホスティング: エラードキュメントを
index.htmlにします。 - Cloudflare Pages: SPA フォールバックが既定で有効です。
4. サーバーを Lambda / コンテナに置く
dist/server/index.mjs は PORT で待ち受ける Node の HTTP サーバーです(マニフェストの
runtime は "node")。Node プロセスが動く環境にそのまま置けます。
- コンテナ(Cloud Run / ECS·Fargate / Render / Fly など):
node dist/server/index.mjsを 起動コマンドにし、PORTを渡します。 - AWS Lambda: 待ち受け型の Node サーバーなので、コンテナイメージ + AWS Lambda Web Adapter など「HTTP サーバーをそのまま Lambda で動かす」方式が相性の良い選択です。
- シークレット(DB 接続情報や API キー)はサーバー側の環境変数として渡します。これらは
ApiContext.envからのみ読め、クライアントには決して届きません。
AWS Lambda へデプロイする(具体例)
生成される dist/server/index.mjs は PORT で待ち受ける Node の HTTP サーバーです。一方
Lambda は「イベントでハンドラを呼ぶ」モデルなので、待ち受け型のサーバーをそのまま動かすには
AWS Lambda Web Adapter(LWA)を挟むのが
素直です。LWA が Function URL / API Gateway のイベントを、ローカルで動く HTTP サーバーへ
プロキシします。Vantage 側のコード変更は不要です。
1. コンテナイメージで動かす(推奨)
esbuild が dist/server/index.mjs に単一ファイルとしてバンドルするため、node_modules を
持ち込む必要はありません。
# Dockerfile
FROM public.ecr.aws/docker/library/node:20-slim
# Lambda Web Adapter を拡張として同梱(バージョンは適宜更新)
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.1 /lambda-adapter /opt/extensions/lambda-adapter
WORKDIR /var/task
# dist/ ごとコピー(server は ../client を参照するためレイアウトを保つ)
COPY dist ./dist
# LWA と Node サーバーの待受ポートを一致させる(LWA の既定は 8080)
ENV PORT=8080
CMD ["node", "dist/server/index.mjs"]
vantage build # dist/ を生成
docker build -t vantage-api .
# ECR にログインして push(<acct> / <region> は自分の値に)
aws ecr get-login-password --region ap-northeast-1 \
| docker login --username AWS --password-stdin <acct>.dkr.ecr.ap-northeast-1.amazonaws.com
docker tag vantage-api <acct>.dkr.ecr.ap-northeast-1.amazonaws.com/vantage-api:latest
docker push <acct>.dkr.ecr.ap-northeast-1.amazonaws.com/vantage-api:latest
この image で Lambda 関数を作成し、Function URL を有効にすると HTTPS エンドポイントが
得られます。これを CloudFront の /api/* オリジンにするか、フロントの PUBLIC_API_BASE_URL に
直接指定します。
2. Lambda の環境変数を設定する
サーバー設定とシークレットは Lambda の環境変数として渡します(クライアントには届きません)。
| 変数 | 例 | 用途 |
|---|---|---|
CORS_ORIGIN |
https://d111111abcdef8.cloudfront.net |
フロントのオリジンを許可 |
CORS_CREDENTIALS |
true |
Cookie / 認証情報を使う場合のみ |
SECRET_* など |
sk_live_xxx |
ApiContext.env から読むシークレット |
PORT は Dockerfile で設定済みです(LWA の既定 8080 に合わせています)。
3. フロントから Lambda を指す
フロントのビルド時に、Lambda(または前段の CloudFront)のオリジンを PUBLIC_API_BASE_URL に
指定します。
vantage build --api-base-url https://d111111abcdef8.cloudfront.net
apiUrl("/api/monthly-analysis") はこのオリジンに /api/monthly-analysis を連結して呼びます。
本番の環境変数のまとめ
境界は接頭辞で決まります(環境変数も参照)。
| 種類 | どこで設定 | いつ効く | 例 |
|---|---|---|---|
| クライアント公開値 | ビルド時(.env / --api-base-url) |
ビルドに焼き込み | PUBLIC_API_BASE_URL |
| サーバー設定 | サーバーの環境変数 | 起動時に読む | PORT, CORS_ORIGIN, CORS_CREDENTIALS |
| シークレット | サーバーの環境変数 | 起動時に読む(ApiContext.env) |
SECRET_API_KEY など |
デプロイ前チェックリスト
-
vantage checkがエラーなしで通る -
vantage build(分離構成なら--api-base-url付き、または.envにPUBLIC_API_BASE_URL) -
vantage previewでローカル動作を確認 - 分離構成なら、サーバー側に
CORS_ORIGIN(フロントのオリジン)を設定 - 静的ホスティング側で SPA フォールバック(未知パス →
index.html)を設定 - シークレットはサーバーの環境変数にのみ置く(クライアントに出さない)
次に読む
- CLI リファレンス —
buildのフラグを含む全コマンド - 環境変数 — 公開値とシークレットの境界