LoginSignup
0
0

More than 1 year has passed since last update.

PaaSを使ってクライアント/サーバーサイドAppをデプロイしよう

Last updated at Posted at 2023-01-31

クライアント/サーバーサイドを両方使うAppを、PaaSにデプロイする方法について、概要を紹介します。
実践した環境は下記の通りです。

  • Next.js/Phaser/MaterialUI
  • Express + Node.js
  • GoogleAppEngine

他のサービスでも同様にデプロイが可能なように、仕組みの全体像や大まかな概念について解説します。

【結論】クライアントとサーバーサイドで別々のGAEインスタンスを構築する

こういった構成でアプリを作りたい場合は、それぞれについてGAEインスタンスを構築して、アップロードしなければなりません。
そのため通信を行う際には、CORSの設定が必要ですし、各インスタンスに環境変数を設定する必要があります。
ただこの方法、わかる人にとっては当然なようです。
しかし初学者にとっては、日本語ではっきりと名言している文献は皆無なので、気づくのは厳しいかもしれません。

【POINT1】サーバーサイド側にCORS設定を追加する

クライアント側からのアクセスを受け入れるように、CORS設定をしておきましょう。

sample.ts
const io = new Server(httpServer, {
  cors: {
    origin: [
      'http://localhost:3000',
      'https://frontend-bombattacker.an.r.appspot.com',
    ],
  },
});

【POINT2】クライアント側に環境変数を設定する

クライアント側の環境設定として、アクセス先のURLを記述します。
app.yamlに下記を記述することで解決できます。

app.yaml
env_variables:
  NODE_URL: "https://~~~~~"

【POINT3】他のPaaSでも同様の仕組みで実装可能

上記の内容は、他のPaaSでも似たような仕組みによって成り立っています。
つまり、1つのサーバーにデプロイするのではなく、クライアントとサーバーサイドをそれぞれデプロイします。
しかしその組み合わせは、今回のように両方ともGAEにデプロイせずとも可能です。

例)
クライアント・・・Vercel
サーバーサイド・・・Heroku

環境変数の設定方法については異なるので、使いたい環境に応じて調べてみてください。

GAEの機能と動作する基本の流れ

GAEは大まかに下記のような処理により動作しています。

app.yamlの準備

このファイルがあるディレクトリ以下のファイルをアップロードします。
自分は下記のように作成しました。

app.yaml
runtime: nodejs16 // バックエンドの環境
automatic_scaling: // 無料枠を超えないための設定
  min_idle_instances: automatic
  max_idle_instances: 1
  min_pending_latency: 3000ms
  max_pending_latency: automatic
  max_instances: 2
env: standard // スタンダードかフレキシブル
instance_class: F1 // インスタンスの規模

なお、.gcloudignoreというファイルも自動的に生成されます(多分)。
node_modulesや.gitなどをアップロードしないように設定します。

サーバーにファイルをアップロードする

GoogleSDKをインストールすると、gcloudコマンドが使用できるようになります。
これがアップロードの起点になります。

gcloud init // 初期化・インスタンスへの接続
gcloud app deploy // アップロード

Docsでは上記が紹介されていますが、他にもオプションがあるようです。
なお下記にもある通り、アップロードする前にはローカル上でbuildコマンドを使っておく必要があります。

npm installを実行する

アップロードされた後、まず自動的にnode_modulesが展開されます。
ですので同ディレクトリのアップロードは不要です。

npm run startまたはnode server.jsを実行する

起動コマンドを実行します。
ここが第一にハマる点かもしれません(自分はハマった)。
startコマンドの指定がなければルート上にあるserver.jsを探しに行くので、「何度やっても起動しない!」となります。
特にクライアント側を起動する場合、startコマンドが必須です。

過去のアップロードを上書きしてバージョン管理

アップロードしたファイルは常に全て上書きされます。
ダッシュボードでは、下記を行うことができます。

  • バージョン管理
  • バージョンの削除
  • トラフィックの割り当て
  • トラフィックの移行

GAEやその他PaaSなどでできないこと

下記についてはできませんでした(IaaSなどサービスによっては可能かもしれません)。

  • 1つのインスタンスでクライアントとサーバーサイドの両方を動かすことはできない
  • npm installを複数のディレクトリ下で走らせることはできない(最初のみ)
  • サーバー上でbuildコマンドを走らせることはできない
  • サーバー上でtscコマンドを走らせることはできない

【番外編】デプロイやビルドを便利にするパッケージ

npm-run-all

複数のnpmコマンドを同一のターミナルから走らせることができます。
クライアントとサーバーサイドで別々のnode_modulesを使う構成だったので、こちらのパッケージが便利でした。
以下の例だと、npm run devコマンド1つで、クライアントとサーバーサイド両方の起動を行うことができます。
ターミナルも1つあればOK。

package.json

  "scripts": {
    "dev": "run-p dev:*",
    "dev:serve": "cd server && npm run dev",
    "dev:client": "cd client && npm run dev",
    "build": "run-p build:*",
    "build:serve": "cd server && tsc",
    "build:client": "cd client && npm run build",
    "start": "run-p st:*",
    "st:serve": "cd server && node dist/index.js",
    "st:client": "cd client && npm run start"
  },

まとめ・感想

インフラ周りを学習してみて感じたこと。

  • PaaSはどれもほとんど同じ仕組みで動いているみたい
  • 1つやり方を覚えればある程度は代用が効く
  • 2つのインスタンスに別々にデプロイのは発想さえできなかった
  • フロント側は静的ファイルだけで動くわけではない(勘違いしてた)
  • package.jsonのscriptの便利さを実感

謝辞

今回の学習内容は、Recursionのチーム開発に参加して得られたものです。
貴重な場を提供してくださり、ありがとうございます。

またチームメンバーのKohさん・Hayatoさん。
Kohさんは上記アイディアを指摘してくれて本当に感謝です。
1人では間違いなく、期日内にデプロイまで到達できなかったです。
Hayatoさんには今思えば最後はやや無茶振りでしたが、ぜひ今後に活かしてもらいたいです。

その他、チームVとXの皆さま。
やり取りがとても参考になりました。
改めてお礼申し上げますm(_ _)m

ではまた、これからも良きプログラミングライフを。

※曖昧な点、間違いなどありましたら、ぜひご指摘ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0