Edited at

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

More than 1 year has passed since last update.


概要

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に対応したので追記