LCL Engineers' Blog

バス比較なび・格安移動・バスとりっぷを運営する LCLの開発者ブログ

Railsのデプロイ時にwebpackのビルドを実行する

弊社が運営しているサービス:夜行バス比較なびのサーバーサイドはRuby on Railsですが、フロントエンドの一部はReact & ES2015で書かれています。今回はデプロイにおけるRailsとwebpackの連携について紹介します。

www.bushikaku.net

React & ES2015導入の詳細もブログで公開しています。ぜひ読んでみてください。

techblog.lclco.com

これまでの問題

webpackの環境は、各自の開発PC(Mac)につくります。 もともとRailsのsprocketsを使っていたため、React化(ES2015化)完了までは今まで通りsprockets を使うことにしました。 つまり、webpackで書き出したファイルを、sprocketsで管理しているディレクトリ以下へコミットしてしまいます。 (良い方法ではないと思いますが、サーバーにnode.jsの環境を作るまでのつなぎです。)

このように上記の記事でも言及していますが、今までwebpackのビルドは開発者がローカルで実行して、生成されたjsファイルもGitで管理していました。ソースコードの二重管理は手間ですし、手順が多いということはミスの誘発につながるため避けたいところです。

解決策

タイトルのとおり、デプロイ時にサーバーでwebpackを実行するようにしました。具体的にはAsset PipelineのPrecompileにフックしてビルドを実行しています。ビルド後はsprocketsに任せてダイジェストの付与を行っています。

この方法は下記の記事を参考にさせていただきました。

WebPackを使ってRailsからJavaScriptを楽に良い感じに分離する - Qiita

設定の詳細は以下のとおりです。

各種バージョン

Ruby 2.1.2
Rails 4.1.5
node.js 6.9.1
babel 6.11.4
webpack 1.13.1

ディレクトリ構成

webpackの入出力のディレクトリを簡単に説明します。実際より簡略化しています。詳細はこちらをご覧ください。

React & ES2015のソースコードはfrontend/src/scripts/に配置しています。

frontend
├── src
    └── scripts
        ├── xxxx
        │   └── xxxx
        │       ├── xxxx.jsx
        │       └── xxxx.jsx
        ├── xxxx     
        │   ├── xxxx
        │   │   └── xxxx.js
        │   │   └── ...
...

ビルドしたファイルはapp/assets/javascripts/es/にbundleされて出力されます。

app
├── assets
    ├── javascripts
        ├── es
        │   └─ xxxx.js
        │
        ├── xxxx // 通常のjsファイルがあるディレクトリ
        │   └─ xxxx.js
...

gitignoreの設定

ビルドで生成されるjsファイルのバージョン管理は不要になるのでgitignoreに追加します。この場合はapp/assets/javascripts/es/配下を無視します。

Precompileへwebpackビルドのフックを追加

lib/tasksにRakeタスクを作成します。これでデプロイ時にwebpackのビルドが実行され、その後sprocketsで処理され配信されます。

task :build_frontend do
  cd 'frontend' do
    sh 'npm install --production'
    sh 'npm run build'
  end
end

Rake::Task['assets:precompile'].enhance(%i(build_frontend))

おわりに

この方法で煩わしい手動ビルドからも解放され、デプロイもスムーズに行うことができています。

ここから更にフロントエンドの環境を整えてより良いサービスを提供していきたいです。