astro-blog-admin には少し珍しいデプロイ方式があります。1 つのリポジトリ、1 つのブランチを、Cloudflare Pages と Tencent EdgeOne Pages の 2 プラットフォームへ同時にデプロイし、両側で機能は対等、インターフェースは同一です。本稿では内蔵の画像ホスティングが 2 プラットフォームにどう着地したか、そして二重プラットフォームが開発にもたらす利点と教訓を扱います。
画像ホスティング:アップロードして、リンクを得る、それだけ
公開アップロードページ
サイトのルートパスはログイン不要の公開アップロードページです。画像を選んで、アップロードして、リンクを得る——それだけ。管理も設定変更もできません。管理画面内の画像ページには管理機能が加わります:大きなプレビュー、チェックボックスでの一括削除、ライトボックスでの原寸表示。アップロード時、PNG/JPG は空間の節約のためにブラウザ側で先に WebP へ変換され、進捗はページ上部の細いバーが複数並ぶ形で示され、完了すると自動で消えます。
リンクの規則
画像の URL はルート相対のみ:/<接頭辞>/<ファイル名>、ドメインを含みません。接頭辞は設定でカスタマイズでき、どのドメインで開くかは関係ありません——ドメインやプラットフォームを変えても、記事に書かれた画像 URL はそのまま動きます。同名ファイルの再アップロードは上書きせず、自動で連番を付けて改名されます。
二重ストレージ:1 つのインターフェース、2 つのバックエンド
ストレージ抽象化レイヤー
アップロード、読み取り、一覧、削除はすべて統一されたストレージ層を通り、設定に応じて振り分けられます。Cloudflare 側ではバインドされた R2 バケットを優先し、なければ S3 互換 API を使い、EdgeOne 側ではプラットフォーム標準の Blob ストレージを使います。設定ページの第 2 ティアの呼び名までプラットフォーム対応で、Cloudflare では「Cloudflare R2」、EdgeOne では「EdgeOne Blob」と表示されますが、保存される設定値は同じで、両側は互いに影響しません。
切替で移行はしない
2 つのストレージは独立しています。R2 に上げた画像は Blob に切り替えると見えず、戻すとまた見えます。この「自動で引っ越さない」設計は意図的です——ストレージはプラットフォームの資産であり、コードの仕事は今動いているプラットフォームで物事を正しく行うことだからです。
二重プラットフォーム展開
ビルド時のプラットフォーム判定
ビルドコマンドは両側で同一です。コードはビルド時に、プラットフォームが注入するマーカー変数から「自分がどこにいるか」を判定し、その結果を成果物に焼き込んで、実行時にプラットフォーム別のストレージと設定読み込みへ分岐します。1 つのコードベース、1 つのブランチ、2 回のデプロイ。似たようなリポジトリを 2 つ保守する必要はありません。
教訓:変数が先、コードは後
二重プラットフォーム最大の落とし穴はコードではなく設定にあります。環境変数に関わる変更は、まずプラットフォーム側で変数を変更し、読み戻して検証してから、コードをプッシュしなければなりません——プッシュ即デプロイなので、順序が逆だと本番がしばらく変数不足の状態で動くことになります。各プラットフォームの変数は独立しているため、この規律は 2 回実行する必要があります。
この 6 本のシリーズはここまでです:ブログ本体、多言語、コンテンツの形、管理画面の概要、ビジュアル編集、画像ホスティングとデプロイ。どちらのプロジェクトもオープンソースです。GitHub リポジトリで今の姿をぜひ見てみてください。
