[JavaScript] 3D ROOM制作 9日目 Surge・Firebase・GitLab Pages配置 + ポータル3D判定修正

[JavaScript] 3D ROOM制作 9日目 Surge・Firebase・GitLab Pages配置 + ポータル3D判定修正

今日やったこと

  • Surge.sh に WIRED ROOM をデプロイ(7サーバー目)
  • Firebase Hosting に WIRED ROOM をデプロイ(8サーバー目)
  • GitLab Pages に WIRED ROOM をデプロイ(9サーバー目)
  • Fly.io を試みたが無料枠廃止で断念
  • ポータル近接判定のY座標バグ修正
  • duplex部屋のカスタマイズ(Firebase)
[JavaScript] 3D ROOM制作 9日目 Surge・Firebase・GitLab Pages配置 + ポータル3D判定修正 [JavaScript] 3D ROOM制作 9日目 Surge・Firebase・GitLab Pages配置 + ポータル3D判定修正 [JavaScript] 3D ROOM制作 9日目 Surge・Firebase・GitLab Pages配置 + ポータル3D判定修正 [JavaScript] 3D ROOM制作 9日目 Surge・Firebase・GitLab Pages配置 + ポータル3D判定修正

Surge.sh デプロイ(7サーバー目)

Surge.sh は npm ベースの超シンプルなホスティング。デプロイは一発。

cd ~/github/ROOM_SURGE
npx surge . wired-room-surge.surge.sh

これだけ。アカウント作成もコマンドライン上で完結する。

Surge.sh の CORS 問題

デプロイは一瞬だったが、CORS ヘッダーに非対応

$ curl -I https://wired-room-surge.surge.sh/banner.webp
HTTP/2 200
content-type: image/webp
# ← Access-Control-Allow-Origin がない

_headers ファイルも CORS 設定用のファイルも仕組みがない。有料プラン(30ドル/月の Professional)なら CORS 設定できる可能性があるが、ROOM 1つのために月30ドルは論外。

結論:単体アクセスは問題ないが、ポータルネットワークからのバナー画像取得ができない。 他サーバーから Surge の部屋のバナーは読めない。Surge から他サーバーへの接続は可能(自分からのリクエストには CORS 関係ない)。

deploy alias

# ~/.bashrc
alias deploy-surge='cd ~/github/ROOM_SURGE && surge . wired-room-surge.surge.sh'

Firebase Hosting デプロイ(8サーバー目)

Firebase Hosting は Google の CDN で配信される。セットアップは Surge に比べると手順が多い。

インストールとセットアップ

npm install -g firebase-tools
firebase login
firebase init hosting

firebase init で聞かれる設定:

  • Public directory: .(ルート直下にファイルがある)
  • Single-page app: No
  • GitHub auto deploys: No

CORS 設定(firebase.json)

Firebase は firebase.jsonheaders セクションで CORS を設定する。

{
  "hosting": {
    "public": ".",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "headers": [
      {
        "source": "**/*",
        "headers": [
          {
            "key": "Access-Control-Allow-Origin",
            "value": "*"
          }
        ]
      }
    ]
  }
}

デプロイ

firebase deploy
$ curl -I https://wired-room-lain-5a04a.web.app/banner.webp
HTTP/2 200
access-control-allow-origin: *
content-type: image/webp

CORS ヘッダー確認。Google CDN なのでレスポンスも速い。

duplex 部屋のカスタマイズ

Firebase の部屋には SrMonteiro 作の duplex モデル(CC-BY-4.0)を採用。2階建て吹き抜けの現代建築で、ガラス窓から差し込む光がリッチ。

  • クレジットボードにアスキーアート(ハート+猫)を配置
  • 元あった個人連絡先(メール・WhatsApp)は削除
  • 2階の扉前に friend ポータルと works ポータルを設置
  • 階段は斜め移動を駆使すれば登れる(スロープ物理が階段ジオメトリにも効く)

Fly.io 断念

Docker コンテナベースのホスティングとして Fly.io を検討。CLI インストールとアカウント作成まで完了。

curl -L https://fly.io/install.sh | sh
fly auth login

ここでデプロイしようとしたところ、クレジットカード登録が必須であることが判明。

2024年に無料枠(3 shared-CPU VM、3GB ストレージ)が廃止され、新規アカウントはトライアル(2VM時間 or 7日間)のみ。最小構成(shared-cpu-1x、256MB RAM)でも月1.94ドルかかる。

WIRED ROOM は全サーバー無料がポリシーなので断念。Dアニメストアに課金した方がいい。


ポータル近接判定のY座標バグ修正

duplex 部屋で発覚したバグ。1階にいるのに2階のポータルに反応する。

原因

checkPortalProximity() がプレイヤーとポータルの距離をX/Z座標の2D距離で判定していた。

// 修正前(controls.js)
_playerPosXZ.set(S.playerPos.x, 0, S.playerPos.z);

for (const pm of S.portalMeshes) {
    _portalPos.set(pm.position.x, 0, pm.position.z);
    const dist = _playerPosXZ.distanceTo(_portalPos);

Y座標を両方 0 に潰しているため、真上・真下のポータルにも水平距離だけで反応してしまう。平屋の部屋では問題にならなかったが、duplex のような多層モデルで顕在化した。

修正

3D距離判定に変更。

// 修正後
_playerPosXZ.set(S.playerPos.x, S.playerPos.y, S.playerPos.z);

for (const pm of S.portalMeshes) {
    _portalPos.set(pm.position.x, pm.position.y, pm.position.z);
    const dist = _playerPosXZ.distanceTo(_portalPos);

2行の変更で修正完了。1階と2階の高低差は PORTAL_TRIGGER_DIST より確実に大きいため、真上のポータルに反応しなくなる。

変数名 _playerPosXZ が実態と合わなくなるが、リネームは任意。


GitLab Pages デプロイ(9サーバー目)

GitLab は GitHub の競合。Git リポジトリ + CI/CD + Pages 公開がセット。

アカウント作成のハードル

GitLab のセットアップは他のサービスに比べて工程が多い。

  1. アカウント作成 — GitHubアカウントでSSO連携
  2. グループ作成fixtan は使えず lain-lab で作成
  3. グループを Public に変更 — デフォルトは Private で、配下のプロジェクトも Public にできない
  4. プロジェクトを Public に変更 — Pages を公開するために必須
  5. Pages のアクセス制御を Everyone に変更 — デフォルトだと認証リダイレクトされる
  6. Personal Access Token 発行 — SSO ログインのためパスワード認証ができず、HTTPSでの push にトークンが必要
  7. アカウント認証 — パイプライン実行に本人確認が必要

GitHub Pages なら push するだけで終わるのに、ここまで検問が多いのは初見殺し。

.gitlab-ci.yml

GitLab Pages のデプロイは CI/CD パイプラインで行う。.gitlab-ci.yml をリポジトリに含める。

pages:
  stage: deploy
  script:
    - mkdir .public
    - cp -r * .public || true
    - mv .public public
  artifacts:
    paths:
      - public
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

public/ ディレクトリにファイルを配置すると Pages として公開される仕組み。GitHub Pages の docs/ フォルダに近い。

push とデプロイ

cd ~/github/ROOM_GITLAB
git init
git remote add origin https://gitlab.com/lain-lab/ROOM_GITLAB.git
git add .
git commit -m "initial commit"
git push -u origin main

初回パイプラインは「yaml invalid」で失敗。原因はアカウント未認証。認証完了後に再実行で成功。

URL: https://room-gitlab-02c14a.gitlab.io/

CORS は自動対応

GitLab Pages は設定不要で CORS に対応していた。ただし挙動に特徴がある。

# Origin ヘッダーなし → CORS ヘッダーなし
$ curl -I https://room-gitlab-02c14a.gitlab.io/
# Access-Control-Allow-Origin が返らない

# Origin ヘッダーあり → CORS ヘッダーあり
$ curl -I -H "Origin: https://lain-lab.com" https://room-gitlab-02c14a.gitlab.io/
access-control-allow-origin: *

ブラウザからのクロスオリジンリクエストには Origin ヘッダーが自動で付くため、実運用では問題ない。curl で直接叩いたときだけヘッダーが出ないので注意。


各サービスの CORS 設定比較(9サービス)

サービス設定方法CORS備考
GitHub Pages不要デフォルトで有効
Netlify_headers ファイルファイルベース
Vercelvercel.jsonJSON設定ファイル
Cloudflare Pages_headers ファイルファイルベース
Renderダッシュボード GUI_headers は効かない
Deno Deployserve.ts 内のコードコードで完全制御
Surge.sh設定不可有料プランなら可能性あり
Firebasefirebase.jsonJSON設定ファイル
GitLab Pages不要○(自動)Origin ヘッダー付きリクエストにのみ応答

Fly.io(不採用)

サービス設定方法CORS備考
Fly.ioDockerfile + nginx.conf2024年に無料枠廃止。月1.94ドル〜

9サーバー体制

#ホストURLCORS
1Netlifyhttps://lain-lab.com/room/
2GitHub Pageshttps://fixtan.github.io/WIRED_ROOM/
3Vercelhttps://room-vercel.vercel.app/
4Cloudflare Pageshttps://room-cloudflare.fixjp.workers.dev/
5Renderhttps://room-render.onrender.com/aisle/
6Deno Deployhttps://room-deno.lain-lab.deno.net/room01/
7Surge.shhttps://wired-room-surge.surge.sh/
8Firebasehttps://wired-room-lain-5a04a.web.app/
9GitLab Pageshttps://room-gitlab-02c14a.gitlab.io/

CORS 対応 8サーバー + 単体のみ 1サーバー。すべて無料、サーバーサイドコードなし(Deno Deploy の serve.ts を除く)。


リポジトリ