概要
- Herokuではデプロイするためにbuildpackというのを使う
- Node.jsでは
npm script
にstart
を定義しておけば、あとはいい感じにやってくれて嬉しい - よくある構成のアプリだと、簡単にデプロイできる一方で、独自のオレオレ構成アプリはデプロイが大変!(ていうかどうやるんだろう)
- Node.jsでは
- buildpackを自作してしまったらよいのでは?
- 試しにやったら結構苦労した
想定される構成
フロントエンド(SPAの静的なファイル)とバックエンド(WebAPI)の組み合わせです。
Herokuでは静的なファイルを配信するためにもNginxやそれに類する静的ファイル配信用のアプリケーションを用意して、そこで配信する必要があります。
ここで、この問題に対応するためには以下のようなソリューションが考えられるでしょう。
- WebAPIの特定のパスにアクセスする場合は静的ファイルを配信できるように実装する
- 静的ファイルはNetlifyとかで配信して、HerokuではWebAPIだけ載せる(CORS対策ちゃんとする)
- Dockerイメージに固める
- Herokuのインスタンス内に2つのプロセスを立ち上げて、静的ファイル配信とWebAPIを共存させる
1, 2はダルかったので、3か4で、おそらく簡単で正しいのは3なのだと思うのですが、buildpackを理解する上でもやっておこうと思い、4を選びました。
実施内容
実際の構成
こんな感じでhttp-serverでリクエストを受けて、それをWebAPIと静的ファイル配信に振り分ける感じです。
自作のbuildpackを使えるようにする
まずは、buildpackを作る前にオレオレbuildpackを使えるようにする方法を確認します。
HerokuのBuildpack APIが参考になるでしょう。
具体的なところは実際のbuildpack(heroku-buildpack-nodejs)をみた方が早かったです。
それを踏まえた上で、自分がやったことは以下の通りです。
- Githubとかにbuildpack用のリポジトリを用意する(今回はアプリのリポジトリをそのまま使うことにした)
- トップレベルにbinディレクトリを用意する
- binディレクトリには
detect
,compile
,release
というシェルスクリプトを用意する - detectで"Monorepo"を出力する
- compileでビルドやサーバーを用意する
- releaseは特になにもしなくていいっぽい
compileでやったこと
実物はこちらです。
https://github.com/naoki-tomita/todo-wasm/blob/master/bin/compile
言語はRustなので、それ特有の処理もやっています。
- Rust関連のツールをインストールする先を
$CACHE_DIR
に設定しておく(ここのディレクトリは永続されるっぽいので、次回以降は早くなる) - rustupというバージョン管理ツールをインストールする
- cargo-webというツールをインストールする
- ビルドされた成果物が
$CACHE_DIR
に出力されるように設定する(次回からはインクリメントビルドが効く) - フロントエンド、バックエンドをビルドする
- ビルドで生成された成果物を
$BUILD_DIR
にコピーしておく(Herokuのインスタンスには、$BUILD_DIR
がコピーされるのでやっとかないと意味ない) - Node.jsを
$BUILD_DIR/.heroku/node
下にインストールする(http-serverを立てるのに必要だった)- インストールというか、Linux用の実行ファイルを公式サイトからダウンロードして解凍しただけ。
.profile.dを用意する
.heroku/node
下にNode.jsをインストールしましたが、当然ながらこれだけでは実行することができません。
パスを通さないといけないのです。しかし、パスを通す方法がわからず、相当苦戦しました。
結論からいうと、.profile.dというフォルダ下(binと同じ階層)に任意のシェルスクリプトを置いておくことで、.bash_profile
的な効果を得られるようです。
そこで、$HOME/.heroku/node/bin
にパスを通すことで、nodeコマンドやnpmコマンドを利用できるようにしました。
Procfileを用意する
Herokuでは、トップレベルの階層にProcfileというファイルを置いて、中にコマンドを書いておけば起動時に実行されます。
したがって、これを使ってhttp-serverとWebAPIを起動することにしています。
できたものがこちらになります。
以上です。よろしくお願いします。