Herokuでexpressを使うときに困ったこと(環境変数、ビルド、ポート)
Herokuにexpress(node)で作ったアプリを動かそうとしたら、立て続けに困ったことが起こったのを調べたことをメモしました。
何度もPRを送るのに気が引けましたが、なんとか乗り越えました。
- 環境変数を設定したい
- ビルドされない
- ビルドが通らない
- アプリが起動しない
「ローカルの開発環境では問題なく動いているのに・・・」というのがモチベーションを打ち砕くのですが、あと少しです。
環境変数を設定したい
やり方は2通りありました。Heroku Cliで設定する方法と管理画面から設定する方法。どちらでもいいので、2通り書きます。
Heroku Cliで設定する
まず、Heroku Cliをインストールする必要があります。
Homebrew がインストールされているなら、以下のコマンドでサクっと入ります。
$ brew install heroku
$ heroku
▸ Add apps to this dashboard by favoriting them with heroku apps:favorites:add
See all add-ons with heroku addons
See all apps with heroku apps --all
See other CLI commands with heroku help
あとは設定するだけです。
$ heroku config:set KEY=VALUE
管理画面から設定する
ログイン後、Setting画面に行くと Config Variables
というメニューがあります。 Reveal Config Vars
というボタンをクリックすると Config Vars
が表示されますので、そこに環境変数をaddしてください。
ビルドされない
設定をしなければ、ビルドはされません。初期状態では npm install
と npm start
だけはやってくれるようでした。
なので、 package.jsonのscriptsにpostinstallを追加してインストール後にビルドを実行するようにします。
以下のような感じです。
{
"scripts": {
"build": "webpack",
"start": "node app.js",
"postinstall": "npm run build"
}
}
これはnpmの機能なのでローカルの開発環境でも npm install
をしたあとにpostinstallが動くようになっているので、確認してみてください。
環境変数の受け取り方
環境変数をコードで受け取るには、 process.env
から受け取ります。環境変数に KEY=VALUE
を設定していると以下のようになります。
$ node
> process.env.KEY
'VALUE'
>
ローカルの開発環境でも確認したい
ローカルで動くか確認するには少し面倒ですが、 node-foremanを使えば簡単です。
$ npm install -D foreman
次に .env
ファイルに環境変数を書きます。
KEY1=VALUE1
KEY2=VALUE2
KEY3=VALUE3
あとは環境変数を読んでからnpmを実行するようにするだけです。
$ node_modules/foreman/nf.js npm start
ビルドが通らない
ローカルでビルドコマンドを叩いても問題ないのだから、大丈夫だと油断しているとハマります。ハマりました。
Herokuはproduction環境なので、package.jsonのdependecies、devDependeciesが正しく登録されていないと、ライブラリが足りずにビルドされません。
ローカルの開発環境で確認するには、npmの設定を変える必要があります。
以下のコマンドで変更して、ビルドをしてみてください。
$ npm config get production
false
$ npm config set production true
$ npm config get production
true
ちなみに、package.jsonの中を入れ替えたりしていると汚くなってしまいますが、 fixpack
を使うと整形してくれるので便利です!
https://github.com/henrikjoreteg/fixpack
使い方は簡単です。npmでグローバルにインストールして、package.jsonのあるディレクトリでコマンドを叩くだけです。
$ npm install -g fixpack
$ fixpack
設定ファイルで自分好みに整形することもできますので、こういうのが気になる人は使ってみてはどうでしょうか。
アプリが起動しない
ビルドも通ったのに、アプリはエラー画面のままでした。管理画面を見ても何も変化はないのです。エラー画面にログを見なさいと書いてあるので見てみましょう。
$ heroku logs --app my-app
my-appのところは自分のアプリ名を入れてください。そうすると、ログがバーっと出てきます。
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
こんなログが出てたら、ポートがあっていない可能性があります。
Heroku側から動的に生成されたポートで動くようにしていなければ、いけないそうです。こんな感じです。
import * as express from 'express'
const app = express ()
app.set ('port', (process.env.PORT || 8080))
app.listen (app.get ('port'), (error: any) => {
console.info (`PORT: ${app.get ('port')}`)
})
これでようやく動くようになりました!