【Netlify + Heroku】Socket.IO アプリのデプロイ
で作成した通信対戦アプリをデプロイするときに結構苦労したので、その記録を書いておきます。
当該のアプリはこちらです。
アプリの構造
Socket.IO を使用して、クライアント-サーバ間で通信をするアプリです。
コードは TypeScript で書き、Webpack を使って、
クライアントのコードはpublic/bundle.js
として、サーバのコードはdist/main.js
としてコンパイルしています。
public
配下の HTML のscript
タグからbundle.js
を読み込み、
ローカルではnode dist/main.js
をターミナルから入力することでサーバのコードを動かしていました。
ディレクトリ構成は、このようになっていました。
# 静的ファイルpublic/# css、画像、音声など- static/- bundle.js- index.html# サーバのコードがコンパイルされたやつdist/- main.js# クライアントのコードsrc/# サーバのコードserver.tspackage.jsontsconfig.jsonwebpack.config.js...
デプロイ方法
public
配下の静的ファイルは Netlify、dist
配下のサーバのファイルは Heroku で動かしています。
以下の図のように、クライアントサイドは Netlify、サーバサイドは Heroku っていう感じです。
おそらく Netlify は静的専用なので、動的なことはできないんだと思います。
この動画を参考にしながらデプロイを進めていきました。
しかし、ここでいくつか問題が発生してしまいました。
問題点
Heroku でビルドできない
Heroku でビルドできなかったので、デプロイログを見ると、package.json
がないとのこと。
Heroku のプロジェクトパスにはdist
を指定しているのですが、その中にはmain.js
しかないからです。
仕方ないのでルートにあったpackage.json
をdist
に移動すると、ビルドできるようになりました。
Heroku で Application error
heroku logs --tail
すると、code=H10 desc=App crashed status=503
なエラー。
ログを遡ると、npm start
でこけてるっぽい。
実はpackage.json
の中身はこうなっていました。
package.json1{2...3"scripts": {4"start": "npx webpack && node dist/main.js"5},6...7}
このファイルのパスをさきほど変えたので、この部分のパスも変えなくてはなりません。
webpack.config.js
をこのdist
ディレクトリに入れてもいいかもしれないですが、
このファイルはクライアントのコードもコンパイルしているし、いろいろ面倒そうなので、
ローカルでnpx webpack
して、npm start
にはnode main.js
だけ載せることにしました。
package.json1{2...3"scripts": {4"start": "node main.js"5},6...7}
これで Heroku 側の 503 エラーはなくなりました。
いまだに Heroku の URL には Not Found と表示されますが、本体は Netlify 側の URL なので問題ないと思います。
ブラウザで CORS エラー
これが一番煩わしかったです。
ブラウザで Netlify の URL にアクセスして、デベロッパーツールのコンソールを開くと、
このエラーが表示されました。
セキュリティ的な意味で、ドメインが違うサイト間で通信するには明示が必要だということです。
さて、困ったのはどこにそれを書けばいいのかわからないということでした。
クライアント側か?サーバ側か?
クライアント側だとすれば、Netlify のnetlify.toml
や_headers
ファイルで HTTP ヘッダを指定することができます。
ところがこれを追加してもうまくいかず…
ということはサーバ側かと思って、Express.js の CORS について調べていろいろ書いてみるも、うまくいかず…
先の動画でもそのコードでも何か特別なことをしているようには見えなかったし、八方塞がりでありました。
ところが、ふと「Socket.IO CORS」で調べると、
なんとバージョンが変わってからは明示的な CORS 設定が必要とか言うじゃないですか。
Netlify の設定ファイルも Express の CORS のコードも必要なく、これだけでヘッダを認識するようになりました。
それで、origin として設定する URL は Netlify の URL にすべきだったのですが、
Heroku の URL にするものだと勘違いしていたため、またもエラー。
よく考えれば Socket.IO の CORS 設定のコード(サーバのコード)は Heroku 側だし、
Heroku 側が Netlify 側をブロックしてるんだから、Netlify の URL を書くべきだったんですね。
これでエラーもきれいになくなり、期待通りに動くようになりました。
お役に立てれば幸いです。
では