Rails
フロントエンド
webpack
webpacker

Rails & Webpackerでフロントエンド開発環境を整える

More than 1 year has passed since last update.

概要

Rails 5.1 から導入されるというwebpackerを試してみます。

Webpackerとは

Webpacker makes it easy to use the JavaScript preprocessor and bundler Webpack to manage application-like JavaScript in Rails. It coexists with the asset pipeline, as the purpose is only to use Webpack for app-like JavaScript, not images, css, or even JavaScript Sprinkles (that all continues to live in app/assets).

It's designed to work with Rails 5.1+ and makes use of the Yarn dependency management that's been made default from that version forward. It's also currently compatible with Rails 5.0 stable but there's absolutely no warranty it will still be in the future. You can either make use of Webpacker during setup of a new application with --webpack or you can add the gem and run bin/rails webpacker:install in an existing application.

要は従来のasset piplineとwebpackをつかったJSアプリケーションを共存させるための仕組みといったところでしょうか。

環境

macOS Sierra 10.12.2
Ruby 2.3.0
Rails 5.0.1

導入

まずはrails new

$ rails new webpacker-sample

webpackerをインストール

Gemfileに追記してbundle install1

diff --git a/Gemfile b/Gemfile
index a8f01f7..1e86672 100644
--- a/Gemfile
+++ b/Gemfile
@@ -19,6 +19,8 @@ gem 'jbuilder', '~> 2.5'
 # Use ActiveModel has_secure_password
 # gem 'bcrypt', '~> 3.1.7'

+gem 'webpacker', github: "rails/webpacker"
+
 # Use Capistrano for deployment
 # gem 'capistrano-rails', group: :development
$ bundle install

するとRakeタスクにwebpacker用のタスクが追加されます。

$ bin/rake -T | grep webpacker
rake webpacker:compile                  # compile javascript packs using webpack for production with digests
rake webpacker:install                  # install webpacker in this application
rake webpacker:install:react            # install everything needed for react

webpacker:install を叩いてみる

$ bin/rake webpacker:install

必要なファイルやコマンド郡が追加されました。

new file:   app/javascript/packs/application.js
new file:   bin/webpack
new file:   bin/webpack-watcher
new file:   bin/yarn
new file:   config/webpack/development.js
new file:   config/webpack/production.js
new file:   config/webpack/shared.js
new file:   vendor/package.json
new file:   vendor/yarn.lock

これでとりあえずwebpackを使う準備が整いました。

package.jsonの中身はこんな感じ。 シンプルにdevDependenciesのみとなっています。

{
  "devDependencies": {
    "babel-core": "^6.21.0",
    "babel-loader": "^6.2.10",
    "babel-preset-latest": "^6.16.0",
    "coffee-loader": "^0.7.2",
    "coffee-script": "^1.12.2",
    "path-complete-extname": "^0.1.0",
    "rails-erb-loader": "^3.2.0",
    "webpack": "beta",
    "webpack-merge": "^2.3.1"
  }
}

ビルドしてみる

ビルドはbin/配下に追加されたbin/webpack,bin/webpack-watcher,webpack:compileを使用します。

$ bin/webpack
Hash: 071bb7221801f498ad46
Version: webpack 2.2.0-rc.3
Time: 400ms
             Asset     Size  Chunks             Chunk Names
    application.js  3.37 kB       0  [emitted]  application
application.js.map  3.34 kB       0  [emitted]  application
   [0] ../app/javascript/packs/application.js 496 bytes {0} [built]

app/javascript/packs/application.jsがビルドされて public/packs/application.jsapplication.js.mapというファイルが生成されました。

ビルド時にはconfig/webpack/*.jsがconfファイルとして使用されます。
また、エントリーポイントはapp/javascript/packs/配下に配置し、それ以外のファイルはapp/javascript/に配置する設計となっているそうです。

例えばカレンダーアプリを作成する場合

app/javascript/calendar/index.js
console.log('Hello, Calendar!')
app/javascript/packs/calendar.js
require('calendar')

のようにファイルを配置してビルドします。

$ bin/webpack
Hash: cafcaf55f1653cfef821
Version: webpack 2.2.0-rc.3
Time: 421ms
             Asset     Size  Chunks             Chunk Names
       calendar.js  3.22 kB       0  [emitted]  calendar
    application.js  3.38 kB       1  [emitted]  application
   calendar.js.map     3 kB       0  [emitted]  calendar
application.js.map  3.35 kB       1  [emitted]  application
   [0] ../app/javascript/calendar/index.js 32 bytes {0} [built]
   [1] ../app/javascript/packs/application.js 496 bytes {1} [built]
   [2] ../app/javascript/packs/calendar.js 20 bytes {0} [built]

プロダクション用にビルドする場合はrake webpacker:compileを使用すると、public/packs/digest.jsonとハッシュ値つきのjsファイルが生成されます。

また、webpackのウォッチ機能を使いたい場合はbin/webpack-watcherを使用します。

インクルード

ビルドしたjsをインクルードするには javascript_include_tagの代わりにjavascript_pack_tagというヘルパーメソッドを利用します。

app/views/layouts/application.html.erb
<%= javascript_pack_tag 'calendar' %>

このメソッドを使うことでproduction環境ではdigest化されたjsがインクルードされるようになります。
production環境以外でdigest化されたjsをインクルードするにはconfig/environments/*.rbに下記のように追記します。

config.x.webpacker[:digesting] = true

webpack-dev-server

こちらのPRで追加されました。
bin/webpack-dev-serverで起動します。
以下のように有効化するとjavascript_pack_taglocalhost:8080(デフォルトポート)でサーブされているjsファイルをインクルードしてくれます。

development.rb
  # Make javascript_pack_tag load assets from webpack-dev-server.
  config.x.webpacker[:dev_server_host] = "http://localhost:8080"

その他

Reactを利用する場合はwebpacker:install:reactというrakeタスクでいい感じにファイルを生成してくれます。
ですがこのあたりはまだまだ変わっていきそう?ですね。
react導入サンプル

所感

まだまだwebpacker自体は開発が始まったばかりですが、すでにこれだけでもフロント開発していけそうな気がします。
ServerSideRenderingする場合はreact_on_rails等と組み合わせて使ってもよさそうです。

参考

http://qiita.com/itkrt2y/items/69c31e695b1b39915d00


  1. Rail 5.1ではrails new --webpackとすると自動で追加されるようです