Rails5.1から追加されると噂のWebpackerを使ってReact.jsを動かす。

  • 50
    いいね
  • 0
    コメント

概要

Rails5.1では webpack が導入され、さらに React がデフォルトで使われるのでは!と噂される今日この頃。
Railsのプロジェクト内にある webpacker を試しに使ってみました。
さらに、この webpacker を使うと React も簡単に使えたので、そちらも試してみました。

環境

項目 説明
OS OS X El Capitan
パッケージ管理 Homebrew
その他 Ruby 2.3, Rails 5.0.1

サンプル環境の準備

まずは webpacker で使用する yarn (javascriptのバージョン管理ソフト)をインストールする。

$ brew install yarn

Railsプロジェクトを作成する。

$ rails new webpacker-sample && cd webpacker-sample

Webpacker をインストール

Gemfile に下記を追加する。

Gemfile
...
gem 'webpacker', github: "rails/webpacker"

gemをインストールする。

$ bundle

インストール後、コマンドが追加されていることを確認する。

$ rake -T | grep webpack

# 以下出力結果
rake webpacker                          # Lists available tasks under webpacker
rake webpacker:compile                  # Compile javascript packs using webpack for production with digests
rake webpacker:install                  # Install webpacker in this application
rake webpacker:install:angular          # Install everything needed for Angular
rake webpacker:install:react            # Install everything needed for react
rake webpacker:install:vue              # Install everything needed for Vue

webpackを使う準備(インストール)をする。

$ rake webpacker:install 

# 以下のファイルが生成される

      create  app/javascript
      create  app/javascript/packs/application.js
       exist  bin
      create  bin/webpack-dev-server
      create  bin/webpack-watcher
      create  bin/webpack
      create  bin/yarn
      create  config/webpack
      create  config/webpack/development.js
      create  config/webpack/production.js
      create  config/webpack/shared.js
      append  .gitignore
         run  ./bin/yarn add --dev webpack@beta webpack-merge webpack-dev-server@beta path-complete-extname babel-loader babel-core babel-preset-latest coffee-loader coffee-script rails-erb-loader from "."

# この後、yarnのパッケージインストールのログが出力されますが、長いので省略。

動作確認

サンプルページの作成を作成し、webpackでbuildして表示確認をする。

まずは、サンプルページを作成。

$ rails g controller pages index

# 以下出力結果
Running via Spring preloader in process 85513
Expected string default value for '--jbuilder'; got true (boolean)
Expected string default value for '--helper'; got true (boolean)
Expected string default value for '--assets'; got true (boolean)
      create  app/controllers/pages_controller.rb
       route  get 'pages/index'
      invoke  erb
      create    app/views/pages
      create    app/views/pages/index.html.erb
      invoke  test_unit
      create    test/controllers/pages_controller_test.rb
      invoke  helper
      create    app/helpers/pages_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/pages.coffee
      invoke    scss
      create      app/assets/stylesheets/pages.scss

app/views/layouts/application.html.erbjavascript_include_tagjavascript_pack_tag というヘルパーメソッドに変更する。

app/views/layouts/application.html.erb

<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

webpackでbuildする。

$ bin/webpack

# 以下出力結果
Hash: 071bb7221801f498ad46
Version: webpack 2.2.0
Time: 1771ms
             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]

Railsサーバ起動後

$ rails s

起動が確認されたら http://localhost:3000/pages/index にアクセスする。
下記のような画面に右側のコンソールに Hello World from Webpacker と出力されていればコンパイルされ無事に読み込まれています。

スクリーンショット 2017-01-18 20.39.01.png
(buildされる /app/javascript/packs/application.jsには console.log("Hello World from Webpacker") と記述してあります。)

あとは、 app/javascript/packs/application.js 内にjavascriptを記述していけばOKです。

Reactを動かす

Reactをインストール

$ rake webpacker:install:react

# 以下出力結果
Replacing loader presets to include react in /Users/yoshi/works/ruby/local/webpacker/wp-sample/config/webpack/shared.js
Replacing loader test to include react in /Users/yoshi/works/ruby/local/webpacker/wp-sample/config/webpack/shared.js
Copying react example to app/javascript/packs/hello_react.js
yarn add v0.19.1
warning No license field
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 10 new dependencies.
├─ babel-helper-builder-react-jsx@6.21.1
├─ babel-plugin-syntax-flow@6.18.0
├─ babel-plugin-syntax-jsx@6.18.0
├─ babel-plugin-transform-flow-strip-types@6.21.0
├─ babel-plugin-transform-react-display-name@6.8.0
├─ babel-plugin-transform-react-jsx-self@6.11.0
├─ babel-plugin-transform-react-jsx-source@6.9.0
├─ babel-plugin-transform-react-jsx@6.8.0
├─ babel-preset-react@6.16.0
└─ esutils@2.0.2
warning No license field
✨  Done in 8.11s.
yarn add v0.19.1
warning No license field
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning "react-dom@15.4.2" has unmet peer dependency "react@^15.4.2".
[4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 15 new dependencies.
├─ asap@2.0.5
├─ core-js@1.2.7
├─ encoding@0.1.12
├─ fbjs@0.8.8
├─ iconv-lite@0.4.15
├─ is-stream@1.1.0
├─ isomorphic-fetch@2.2.1
├─ loose-envify@1.3.1
├─ node-fetch@1.6.3
├─ promise@7.1.1
├─ react-dom@15.4.2
├─ react@15.4.2
├─ setimmediate@1.0.5
├─ ua-parser-js@0.7.12
└─ whatwg-fetch@2.0.1
warning No license field
✨  Done in 16.58s.

Reactのインストールで以下のようなサンプルファイルが生成される。

app/javascript/packs/hello_react.jsx
import React from 'react'
import ReactDOM from 'react-dom'

class Hello extends React.Component {
  render() {
    return <div>Hello {this.props.name}!</div>
  }
}
document.addEventListener("DOMContentLoaded", e => {
  ReactDOM.render(<Hello name="React" />, document.body.appendChild(document.createElement('div')))
})

生成されたサンプルファイル hello_react.js を読み込むように変更をする。

app/javascript/packs/application.js
require('./hello_react.jsx')

webpackでbuildする。

$ bin/webpack

Railsサーバ起動後

$ rails s

起動が確認されたら http://localhost:3000/pages/index にアクセスする。
下記のようなに Hello React! と表示されていればbuildされ無事に読み込まれています。

スクリーンショット 2017-01-18 20.51.20.png

あとは、app/javascript/packs/hello_react.js にReactを記述できます。
(または app/javascript/packs/application.js に記述もできる。)

より便利に使う(ビルドサーバ起動)

このままでは、変更を加えるたびに bin/webpack でbuildしないと反映されません。
そこで下記の手順で webpack のbuildサーバを起動させ、自動で変更が反映されるようにします。

まずは、buildされたコードにアクセスできるように、Railsの設定ファイルに変更を加えます。

webpackをインストールしたときに Rails.application.configure のブロック内に以下のようなコメントが追記されています。

config/environments/development.rb

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

  ...

end

config.x.webpacker[:dev_server_host] = "http://localhost:8080"のコメントを外して保存してください。

変更が終わったら、build用のサーバを起動します。
これでファイルを保存するたびにbuildが自動で行われます。

$ bin/webpack-dev-server

また、別のターミナルを起動し、Railsサーバも同時に立ち上げます。

$ rails s

これでファイルに変更があってもサイトに自動で反映されるようになります。(Railsサーバは別に起動が必要です。

注意点

yarn のインストールについて

yarn(javascriptパッケージ管理)がインストールされてなくてもwebpackerbundle installは正常に実行されます。(エラーが発生しません。)必ずyarnをインストールしてから webpackerのインストールを行ってください。

webpack, yarnコマンドの実行について

webpackコマンドを実行時には必ず先頭にbin/をつけてください。
またyarnのコマンドで新たにパッケージを追加するときも必ず先頭にbin/をつけてください。

bin/をつけないとwebpackerのwebpackコマンド(yarnコマンド)と認識されず、webpackerの意図した場所(ディラクトリ)にbuild(インストール)されません。

コマンド実行例
# webpackコマンド実行
$ bin/webpack
$ bin/webpack-dev-server

# yarnコマンド実行例
$ bin/yarn add bootstrap

参考サイト

http://qiita.com/hiyamamoto/items/e0a30b4799314174b80f
https://github.com/rails/webpacker

追記

2017/01/21 webpack-dev-server の設定方法の箇所に変更を加えました。
2017/01/22 注意点を追加しました。
2017/03/20 プルリクを反映(reaceインストール時に書き出されるファイル名の修正)
2017/03/20 WebpackerがAngular, Vueに対応したので追記