ども、@kimihom です。 この記事は Heroku Advent Calendar 8日目の記事です。まだ3枠空きがありますので、Heroku ユーザーの方はぜひご登録を!
Rails 5.1 から Yarn のサポートが入り、フロントエンドの JavaScript ライブラリの管理が容易になった。そこで Rails 5.1 で作った破壊的イノベーションを生むアプリを意気揚々と Heroku へデプロイしようとしたところ、色々詰まったので残しておく。
遭遇した問題と対応
Rails 5.1 の Yarn サポートにより、yarn install
を実行しないといけなくなった。
しかし、 Heroku の Ruby ビルドパックに yarn install
のコマンド実行が入っていないので、git push
した時点で JavaScript パッケージをインストールしてくれない問題が発生した。結果、JavaSciript を読み込むことができず Heroku 側で JavaScript エラーが発生してしまった。
こういう時こそ Release Phase の出番かと思ってやってみたけど、うまくいかず。
色々と調べていると、Node.js のビルドパックを追加する方法があった。具体的には
heroku buildpacks:add --index 1 heroku/nodejs
とすることで、 heroku/ruby の前に nodejs のビルドパックを埋め込んでくれるようだ。ビルドパックを複数指定して、git push heroku master
後にその順番でビルドしてくれる。そうすれば、Node.js のビルドパックには yarn.lock
を読み込んで node_modules
を生成してくれるので、デプロイがうまくいく。実際に以下のコマンドを叩いてみると、
$ heroku buildpacks === my-awesome-app Buildpack URLs 1. heroku/nodejs 2. heroku/ruby
といった感じで複数のビルドパックが入っていることが確認できる。この状態で、git push heroku master
をやってやると、Rails ルートにある yarn.lock
を読み込んで勝手にライブラリをインストールし始めてくれる。
$ git push heroku master Counting objects: 7, done. Delta compression using up to 4 threads. Compressing objects: 100% (7/7), done. Writing objects: 100% (7/7), 676 bytes | 0 bytes/s, done. Total 7 (delta 6), reused 0 (delta 0) remote: Compressing source files... done. remote: Building source: remote: remote: -----> Node.js app detected remote: remote: -----> Creating runtime environment remote: remote: NPM_CONFIG_LOGLEVEL=error remote: NPM_CONFIG_PRODUCTION=true remote: NODE_VERBOSE=false remote: NODE_ENV=production remote: NODE_MODULES_CACHE=true remote: remote: -----> Installing binaries remote: engines.node (package.json): unspecified remote: engines.npm (package.json): unspecified (use default) remote: engines.yarn (package.json): unspecified (use default) remote: remote: Resolving node version 8.x... remote: Downloading and installing node 8.9.1... remote: Using default npm version: 5.5.1 remote: Resolving yarn version 1.x... remote: Downloading and installing yarn (1.3.2)... remote: Installed yarn 1.3.2 remote: remote: -----> Restoring cache remote: Loading 2 from cacheDirectories (default): remote: - node_modules remote: - bower_components (not cached - skipping) remote: remote: -----> Building dependencies remote: Installing node modules (yarn.lock) remote: yarn install v1.3.2 remote: [1/4] Resolving packages... remote: success Already up-to-date. remote: Done in 0.12s. remote: remote: -----> Caching build remote: Clearing previous node cache remote: Saving 2 cacheDirectories (default): remote: - node_modules remote: - bower_components (nothing to cache) remote: remote: -----> Build succeeded! remote: -----> Ruby app detected remote: -----> Compiling Ruby/Rails remote: -----> Using Ruby version: ruby-2.4.2 remote: -----> Installing dependencies using bundler 1.15.2 remote: Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment remote: Warning: the running version of Bundler (1.15.2) is older than the version that created the lockfile (1.16.0). We suggest you upgrade to the latest version of Bundler by running `gem install bundler`. remote: Fetching gem metadata from https://rubygems.org/........... remote: Fetching version metadata from https://rubygems.org/.. remote: Fetching dependency metadata from https://rubygems.org/. remote: Using rake 12.2.1 remote: Using concurrent-ruby 1.0.5 ... 以下 Ruby のビルドパックの実行
その他の方法
どうやら Webpacker を入れておけば、勝手に Yarn のインストールが走る? そうだ。参照元がどこだか忘れたので、もしかしたら間違ってるかも。
ただ自分は AssetPipeline で普通に Rails のフロントエンドを扱いたかったのでそのために Webpacker の形式に最適化することはしたくなかったので、やっていない。
(余談) Webpacker を入れると、以下のコマンドを実行するわけだけども、
bundle exec rails webpacker:install
てすると
app/javascript: ├── packs: │ # only webpack entry files here │ └── application.js └── src: │ └── application.css └── images: └── logo.svg
っていうディレクトリ構成になる。なんかもうこの構成の時点で使いたくなくなるよね。なぜ javascript
の中に css
や svg
が入るのか?そして layouts に <%= javascript_pack_tag 'application' %>
という 記載しなければならないもクールじゃないので使用するのを止めた。今後のアップデートに期待、かな。
終わりに
現在、heroku.yml という機能が Developer Preview で公開されていて、今後は heroku.yml でこの問題が対応できるようになりそうだ。これも注目していきたい。
まだまだ Rails のフロントエンドの開拓は進んでる最中なので、色々と躓くところがあるかとは思う。でもYarn をちゃんと使って JavaScript ライブラリの管理ができれば、それはそれで良いに越したことはない。
Heroku は Ruby の最新版をリリースした数時間後に最新版 Ruby のサポートを発表したり、最新の Rails アプリケーションもどんどんサポートしてくれるので、新しい何かを試すのにいいプラットフォームだと思う。
Rails 5.1 以降のフロントエンド周りの発展にも期待していきたい。