examples/vercel-ssg
概要
fandhe-frontend フレームワークの Vercel 向け正本サンプルです(イシュー #3290)。親ツリー #3282 の Phase 1(#3284〜#3286、#3288)で、Vercel 上での既定方式は SSG → Vercel Build Output API → vercel deploy --prebuilt(案 c)に確定しました(vercel_runtime 1.x は起動時に panic、2.x は依存グラフ上限〔60 件/深さ 6〕を超えるため不採用。詳細な決定記録は本リポジトリの docs/design/vercel-deployment-strategy.md を参照してください)。本サンプルはこの唯一の既定方式を動く形で示します。Vercel 側に Rust ツールチェーンは不要で、ローカルまたは CI でビルドした静的出力を配置するだけです。
examples/ssg-blog(イシュー #501)と同じく crates.io へ公開済みの fandhe-frontend-core / fandhe-frontend-server(v0.4.3/v0.2.6)をバージョン依存として実際に使う「正本」です。
学べること
fandhe_frontend_server::ssg::generate_pagesによる Build Output APIstatic/ディレクトリ(HTML ページ群)の生成fandhe_frontend_server::ssg::generate_assetsによるconfig.json(Build Output API v3)と404.htmlの生成config.jsonのroutesで「ファイルシステムに一致しなければ 404」を表現する方法({"handle": "filesystem"}の後続ルート)- 古いビルド成果物を残したまま
--prebuiltすると意図しない内容が公開されてしまうため、生成前に固定リテラルの出力先(.vercel/output)だけを削除する fail-closed な取り扱い(.vercel/project.json等のvercel link由来ファイルは削除しません) - 既定エスケープ(REQ-1): ページ本文はすべて
text()経由でノード木へ載せ、raw_html()や HTML 文字列の直接組み立ては使いません - Basic 認証 Routing Middleware(opt-in、既定では無効。後述)
前提
- Rust ツールチェーン(
cargo) - crates.io(
https://index.crates.io/https://static.crates.io)への到達性(依存解決に使用します) fw gate --project examples/vercel-ssgを実行する場合は clippy component / cargo-deny が必要です(tools/ci/ensure-gate-tools.shで導入できます)- デプロイを試す場合のみ: Vercel CLI と Vercel アカウント
動かし方
# .vercel/output/ へ Build Output API 形式の静的サイトを生成
cargo run --release
# 生成結果をローカルで確認(任意)
python3 -m http.server -d .vercel/output/static 8000
# ローカルの簡易サーバーでは config.json の routes(404 フォールバック等)は
# 効きません。routes の動作確認は Vercel 上のデプロイ(下記)で行ってください。
# テスト(既定エスケープ回帰・fail-closed 回帰・古い出力の削除を含む)
cargo test
# fw gate(リポジトリルートから実行)
tools/ci/ensure-gate-tools.sh
cargo run -p fandhe-frontend-cli -- gate --project examples/vercel-ssgcargo run --release の実行後、次のツリーが生成されます。
.vercel/output/
├── config.json # generate_assets(Build Output API v3)
├── functions/ # Basic 認証を有効化した場合のみ生成(後述)
│ └── _middleware.func/
│ ├── .vc-config.json
│ └── index.js
└── static/
├── index.html # generate_pages
├── pages/
│ ├── about/index.html
│ └── default-escaping/index.html
└── 404.html # generate_assetsVercel へのデプロイ(--prebuilt)
- Vercel CLI をインストールします(グローバル導入になるため、
npm i -gの実行前に導入元のスクリプトを信頼できるか確認してください)。
npm i -g vercel- プロジェクトを Vercel と紐付けます(
.vercel/project.jsonが作られ、本ディレクトリの.gitignoreで除外済みです)。
vercel link- 静的出力を生成します(Vercel 側では実行されないため、ローカルまたは CI で事前に実行しておく必要があります)。
cargo run --release- ビルド済み出力をそのままデプロイします(Vercel は
.vercel/output/をアップロードするだけで、Rust のビルドは行いません)。
# プレビューデプロイ
vercel deploy --prebuilt
# 本番デプロイ
vercel deploy --prebuilt --prodBasic 認証(opt-in、既定では無効)
examples/vercel-ssg 本体は Basic 認証の Routing Middleware を組み込み済みですが、既定のビルドには含まれません(.vercel/output は本機能導入前とバイト単位で同一です)。有効化するにはビルド時に環境変数 FANDHE_VERCEL_SSG_BASIC_AUTH を正確に 1 に設定してください。未設定時は無効として扱われますが、設定済みで 1 以外の値(0・true・空文字・前後に空白や改行を含む 1 系等)を指定した場合はビルド自体がエラー終了します(無保護の成果物を誤って生成しないための fail-closed な判定です)。
# 1. フラグを立てて生成する(functions/_middleware.func/ が追加で生成される)
FANDHE_VERCEL_SSG_BASIC_AUTH=1 cargo run --release
# 2. 資格情報を Vercel 環境変数として登録する(対話プロンプトで入力。
# preview・production の両方への登録が必要。詳細はデプロイガイド参照)
vercel env add BASIC_AUTH_USER production
vercel env add BASIC_AUTH_PASSWORD production
vercel env add BASIC_AUTH_USER preview
vercel env add BASIC_AUTH_PASSWORD preview
# 3. デプロイする
vercel deploy --prebuilt- 注意 1: フラグなしで再ビルドすると
clean_output_dirによってfunctions/が削除され、無保護の出力に戻ります。 - 注意 2: Deployment Protection(後述)のほうが強い統制です。無効化する前に、Basic 認証が実際に効いていることを確認してください(手順はデプロイガイドの「Deployment Protection が有効なままの Basic 認証確認(必須)」参照)。
- 注意 3: 資格情報(
BASIC_AUTH_USER/BASIC_AUTH_PASSWORD)はリポジトリ・vercel.json・README のいずれにも書かないでください。
fail-closed な設定手順・ミドルウェアの仕組みの詳細は デプロイガイドの「Routing Middleware による Basic 認証」を参照してください。
Deployment Protection(SSO)の注意
新規に作成した Vercel プロジェクトでは、既定で Vercel Authentication(SSO によるデプロイ保護)が有効になっています。有効なままだと、未認証のアクセスはすべて Vercel のログイン画面へ 302 リダイレクトされ、本サンプルの config.json が定義する 404 フォールバックへは到達しません。
- デプロイ内容を一般公開したい場合は、Vercel の Project Settings → Deployment Protection で無効化してください。
- 非公開のまま検証だけしたい場合は、有効のままにしておいて構いません。
- バイパス用トークン等の秘密情報は、リポジトリにも README にも書かないでください。
主要ファイル
| ファイル | 説明 |
|---|---|
Cargo.toml | crates.io バージョン依存 2 件のみ(fandhe-frontend-core / -server)。root workspace から独立した [workspace] members = ["."] |
structure.toml | fw gate が唯一の情報源として読む構造マニフェスト |
clippy.toml | raw_html() 迂回検出ポリシー(templates/default/ と内容同一) |
deny.toml | 依存ポリシー(templates/default/ と内容同一) |
src/main.rs | Build Output API 生成エントリ(layout / build_pages / not_found_page / clean_output_dir + generate_pages/generate_assets 呼び出し)。opt-in Basic 認証(basic_auth_enabled / output_root_assets / ミドルウェア定数群)も含む |
tests/build_output.rs | 既定エスケープ・fail-closed・古い出力削除・シンボリックリンク拒否の回帰、Basic 認証の有効・無効両モードの CLI ブラックボックステスト |
関連ガイド
デプロイ方式の決定根拠は docs/design/vercel-deployment-strategy.md(docs サイト非掲載のため上記はリンクにせずプレーンテキストで参照しています)を参照してください。