Rails + Bower で Heroku にデプロイする


Rails でアプリケーションを開発していく中で、JavaScript のライブラリを使う機会は増えています。Rails との相性で考えると(特に Asset Pipeline 周り)、\*-rails な Gem を使う方が楽ですが、\*-rails は、オリジナルの JavaScript のライブラリの更新に追随するとは限らず、遅れがちです。

こういったところで、自由度がなくなるのはもったいないので、今回は Bower(http://bower.io/) を使って JavaScript のライブラリを管理することにします。

また、今回は Heroku(https://www.heroku.com/) へのデプロイを考えています。Heroku は、 git push 一発でデプロイできるのが売りですが、リポジトリの内容から Rails のアプリケーションであると判断され、Bower に利用に必要な Nodejs の環境が作られません。このあたりの解決方法についても、整理しようと思います。

## 今回利用した実行環境やライブラリのバージョン

```shell
$ bundle exec rake about
About your application's environment
Rails version             4.2.3
Ruby version              2.2.2-p95 (x86_64-darwin14)
RubyGems version          2.4.5
Rack version              1.6.4
...

$ node -v
v0.12.7
$ npm -v
2.11.3
$ bower -v
1.4.1

$ heroku version
heroku-toolbelt/3.41.3 (x86_64-darwin10.8.0) ruby/1.9.3
```

## Bower の設定

まず、Bower の設定ファイルを準備します。.bowerrc にて、コンポーネントのインストール先などを設定しておきます。

```JavaScript:.bowerrc
{
  "directory": "vendor/assets/components",
  "json":      "bower.json"
}
```

続けて、bower.json も用意します。Asset Pipeline 周りも問題を解決する方法の例として、Flat UI(http://designmodo.github.io/Flat-UI/) を使います。

```JavaScript:bower.json
{
  "name": "hoge",
  "version": "0.0.0",
  "authors": [
    "Hoge Hogeo<hoge@example.com>"
  ],
  "license": "MIT",
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "vendor/assets/components",
    "test",
    "tests"
  ],
  "dependencies": {
    "flat-ui": "2.2.2",
    "bootstrap": "~3.3.5",
    "normalize.css": "~3.0.3"
  }
}

```

## Heroku の設定

`heroku create` などは完了している前提で話を進めます。今回、Bower を利用するため、Rails を実行するための Ruby の環境だけではなく、Bower を実行するための Node.js の環境も必要になってきます。このように複数の環境を利用したい場合は、Buildpack というものを指定してあげる必要があります。

https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app

上記のドキュメントに従って、Buildpack を設定してみましょう。まずは、Ruby の環境を設定します。

```shell
$ heroku buildpacks:set https://github.com/heroku/heroku-buildpack-ruby
```

続けて、Node.js の設定を追加します。

```shell
$ heroku buildpacks:add --index 1 https://github.com/heroku/heroku-buildpack-nodejs
```

ここで、`--index 1` により Node.js を 1番目の Buildpack にしています。これは、Asset Pipeline の実行前に、`bower install` を実行して、JavaScript のライブラリをインストールしておきたいためです。

現在の Buildpack の設定は、以下のようにして確認することができます。

```shell
$ heroku buildpacks
=== hoge Buildpack URLs
1. https://github.com/heroku/heroku-buildpack-nodejs
2. https://github.com/heroku/heroku-buildpack-ruby
```

## Bower をインストールし、実行するための設定

Node.js の環境を利用することができるようになったので、自動的に Bower をインストールし、実行するための設定を追加します。このために `package.json` を準備します。

```JavaScript:package.json
{
  "name": "hoge",
  "version": "1.0.0",
  "dependencies": {
    "bower": "~1.4.1"
  },
  "engine": {
    "node": "0.12.x",
    "npm": "2.11.x"
  },
  "scripts": {
    "postinstall": "./node_modules/bower/bin/bower install"
  }
}
```

`scripts` の `postinstall` で `bower install` を実行させている部分が肝です。

## アセットの設定

Bower を利用してインストールしたコンポーネントは、require を使って取り込みます。

```CSS:app/assets/stylesheets/application.css.scss
/*
 ...
 *= require "normalize.css/normalize"
 *= require "bootstrap/dist/css/bootstrap"
 *= require "flat-ui/dist/css/flat-ui"
 */
```

これだけで、ローカルの開発環境は動作すると思いますが、Heroku にデプロイしてみるとうまくいかないところがでてきます。

たとえば、今回の例のように Flat UI を使う場合、Flat UI に含まれているフォントも利用したくなると思います。今回、Bower を利用してインストールするコンポーネントは vendor 配下にインストールするので、Asset Pipeline は自動的にフォントを認識しません。そこで、以下のような設定を追加します。

```Ruby:config/initializers/assets.rb
Rails.application.config.assets.precompile << Proc.new { |path|
  if path =~ /\.(eot|svg|ttf|woff|otf)\z/
    true
  end
}
```

このようにして、Asset Pipeline にのせたとしても、Flat UI 側は、ダイジェストの付いたリソースを考慮していないので使えません。そこで、その設定を上書きする必要があります。以下は、部分的な例です。

```CSS:app/assets/stylesheets/application.css.scss
@font-face {
  font-family: 'Flat-UI-Icons';
  src: asset-url('flat-ui/fonts/glyphicons/flat-ui-icons-regular.eot');
  src: asset-url('flat-ui/fonts/glyphicons/flat-ui-icons-regular.eot?#iefix') format('embedded-opentype'), asset-url('flat-ui/fonts/glyphicons/flat-ui-icons-regular.woff') format('woff'), asset-url('flat-ui/fonts/glyphicons/flat-ui-icons-regular.ttf') format('truetype'), asset-url('flat-ui/fonts/glyphicons/flat-ui-icons-regular.svg#flat-ui-icons-regular') format('svg');
}
```

Flat UI には、他にも Lato というフォントも含まれていますが、こちらもすべて上記のように変更する必要があります。

## Heroku 用の Gem の追加

Heroku で動かすために便利な Gem があるのでインストールしておきましょう。

`rails_12factor`(https://github.com/heroku/rails_12factor) は、Heroku が提供している Gem です。ログやアセット周りを調整してくれます。

```Ruby:Gemfile
group :production do
  gem 'rails_12factor'
end
```

## デプロイしましょう！

ここまで準備して、やっとデプロイすることができるようになりました。`git push heroku master` の出番です！