Rails5.1のwebpack実装、webpacker gem簡単解説

## はじめに

DHHがRails5.1にwebpackを取り入れる意向を示し、その実装として[webpacker gem](https://github.com/rails/webpacker)を提案しました。
まだ最低限の方針が示されただけで機能は全然足りてませんが（コミットチャンスですよ！！）、どんな実装になっているか軽く見てみました。

## リポジトリ, PR

webpacker gem: https://github.com/rails/webpacker
PR to Rails: [Basic --webpack delegation to new webpacker gem](https://github.com/rails/rails/pull/27288)

## 内容

注： あくまで2017/1/18現在の話で、これから多くの変更が入ることになります

- webpackのラッパーになっている
    - webpackを用いたJSアプリの素地を作ってくれる
    - webpackのコマンドをrakeコマンドでラップしている
        - rake越しにやりたくない人は、webpackを直に叩くことももちろん可能
- sprocketsとは役割が違うので、sprocketsを殺す予定はない
    - sprocketsの役割は、view(controller)ごとのassetを用意すること
    - webpackerは個別のJSアプリ（モジュール）を作るのに利用する
        - 例えばカレンダーアプリを作る場合、`app/javascript/packs/calendar.js`をエントリーポイントとした一つのJSアプリを作り、それを組み込むことになる
        - viewごとにファイルが作られると、このようなJSアプリごとのファイルを書きにくかった
- Rails5.1以上に対応するが、開発の都合上、現在は5.0でも動くようになっている
    - [DHH的には5.1以上しか対応するつもりはない](https://github.com/rails/webpacker/issues/32#issuecomment-267840652)
    - 一部のrakeコマンドを割り切れば、多分4.xでも動く
- [sprocketsの`javascript_include_tag`の代わりに`javascript_pack_tag `を使う](https://github.com/rails/webpacker/blob/master/lib/webpacker/helper.rb)
- [コード置き場は`app/javascript/`になる](https://github.com/rails/webpacker/blob/master/lib/install/config/shared.js#L8)
    - `app/assets/`はasset pipelineのためのディレクトリなので、外に出す必要があったのだと思う
    - `app/javascript/packs/`にエントリーファイルを置き、`app/javascript/`にそれ以外を置く形
        - 例えば、`app/javascript/packs/calendar.js`と`app/javascript/calendars/*.js`って形でファイルを置いて、`app/javascript/packs/calendar.js`を起点にコードを書くことになる
    - ディレクトリのネーミングに疑問を覚える人は次のPRについたコメントを読んでください
        - https://github.com/rails/webpacker/pull/2
- [ビルド生成物は`public/packs/`に置かれる](https://github.com/rails/webpacker/blob/ab46a9add8de8e0f42e24b9dd727c38b00f0c870/lib/install/config/shared.js#L16)
- 設定ファイル置き場は`config/webpack/<env name>.js`
    - [lib/install/bin/webpack.tt](https://github.com/rails/webpacker/blob/ab46a9add8de8e0f42e24b9dd727c38b00f0c870/lib/install/bin/webpack.tt#L11)
- rake task
    - `bin/rake webpacker:install`でテンプレートから設定ファイルとか作ってくれる
        - [lib/tasks/webpacker.rake](https://github.com/rails/webpacker/blob/ab46a9add8de8e0f42e24b9dd727c38b00f0c870/lib/tasks/webpacker.rake#L18-L21)
        - [lib/install/template.rb](https://github.com/rails/webpacker/blob/master/lib/install/template.rb)
    - `bin/rake webpacker:compile`でwebpackを使いビルドしてくれる（for production）
        - [lib/tasks/webpacker.rake](https://github.com/rails/webpacker/blob/ab46a9add8de8e0f42e24b9dd727c38b00f0c870/lib/tasks/webpacker.rake#L7-L16)
        - [lib/install/bin/webpack.tt](https://github.com/rails/webpacker/blob/master/lib/install/bin/webpack.tt)
- [開発時の`webpack --watch`は`bin/webpack-watcher`を通して行う](https://github.com/rails/webpacker/blob/master/lib/install/bin/webpack-watcher.tt)

## 参考実装

https://github.com/gauravtiwari/rails-webpacker

このリポジトリを見ればReact, Angular, Vueでの実装例がわかりますので、webpackerを導入する前に一度見てみるといいかも

## 雑感

実装はまだ最低限ですが、webpackをシンプルに利用できるインターフェースが提供されていて非常に良いと思いました。

また、先日「5.1にwebpackが入りそう」という話が出た際に「webpackでいいのか？」という意見が何件か見られましたが、まず大前提としてこの機能はオプションですし、さらにこのwebpacker gemはロックインする何かを作るわけではなさそうなので、webpackが廃れたり別に何かもっといいものが出てきたならば、それはその時に誰かが（あなたが）webpackerと同じように拡張を書けばいいだけだ、ということを伝えるモデルケースとしてもうまくできていると思いました。

さあ、方針はわかったと思うのでみなさんコミットしましょうね