webpacker
https://github.com/rails/webpacker
確認バージョン
- Ruby 2.3.3
- Rails 5.0.1
- webpacker 確認時点でのhash:215cdbc5858309de85d71932aa3468bb76feb4a2
Railsアプリ作成
適当に新規Railsアプリを作る
$ mkdir webpack-sandbox
$ cd webpack-sandbox
$ rails new -T .
Gemfileを変更(追加)
(GitHub指定が無いと rake webpacker:install:react
が使えない)
gem 'webpacker', github: 'rails/webpacker'
インストール & 確認
$ bundle install
$ bundle exec webpack -h
webpack 1.14.0
Usage: https://webpack.github.io/docs/cli.html
Options:
--help, -h, -?
--config
--context
...
テンプレートを生成する
$ bundle exec bin/rails 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 add v0.17.10
info No lockfile found.
...
生成後の構成(特徴的なもののみ抜粋)
.
├── Gemfile
├── Gemfile.lock
├── README.md
├── Rakefile
├── app
│ └── javascript
│ └── packs
│ └── application.js
├── bin
│ ├── webpack
│ ├── webpack-dev-server
│ ├── webpack-watcher
│ └── yarn
├── config
│ └── webpack
│ ├── development.js
│ ├── production.js
│ └── shared.js
└── vendor
├── assets
│ └── javascripts
├── package.json
└── yarn.lock
- package.jsonはvendor配下に配備される
- shared.js → development.js / production.js 両方から参照される
ビルドする
$ bundle exec bin/webpack
Hash: 071bb7221801f498ad46
Version: webpack 2.2.0-rc.4
Time: 482ms
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]
Viewから読み込む
jsの読み込みを変更
<%= javascript_pack_tag 'application' %>
起動してみる
適当にコントローラを作成
$ bundle exec rails g controller Sample index
root to: 'sample#index'
起動
$ bundle exec rails s
上手くいけばコンソールにログが出力される
ダイジェスト値の付与を確認(production起動)
ただこの場合、development環境のため、jsにダイジェスト値が付与されていない。
productionでダイジェストが付与されることを確認してみる。
SERCRET_KEY_BASEを設定
$ bundle exec rake secret
出力されたhash値を設定
$ export SECRET_KEY_BASE={hash}
digestファイルを生成
$ bundle exec rake webpacker:compile
production用ビルド & 起動
$ RAILS_ENV=production bundle exec bin/webpack
$ export RAILS_SERVE_STATIC_FILES=true
$ RAILS_ENV=production bundle exec rails s
ダイジェストが付与されているスクリプトがロードされてますね。
Reactを使う
$ bundle exec bin/rails webpacker:install:react
<%= javascript_pack_tag 'hello_react' %>
$ bundle exec bin/webpack
$ bundle exec rails s
デフォルトで生成されるhello_react.jsのHelloコンポーネントが出力されている。
コンポーネントを追加してみる
適当にコントローラを追加
$ bundle exec rails g controller Count index
衝突しないようにデフォルトのスクリプトを外す
<head>
<title>WebpackerSandbox</title>
<%= csrf_meta_tags %>
</head>
スクリプト作成
import/exportの挙動確認の意味も込めて無意味にネスト
.
├── counter
│ ├── counter.js
│ └── index.js
└── counter.js
import React from 'react'
import ReactDOM from 'react-dom'
import * as counter from './counter/index'
document.addEventListener("DOMContentLoaded", e => {
ReactDOM.render(<counter.Counter />, document.body.appendChild(document.createElement('div')))
})
export * from './counter'
import React from 'react'
export class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: props.count || 0
}
}
handleClick() {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<div>
<div>COUNT: {this.state.count}</div>
<div><input type="button" value="COUNT UP" onClick={() => this.handleClick()} /></div>
</div>
)
}
}
ビルドして動作確認
スクリプトのロードを末尾に追加
<%= javascript_pack_tag 'counter' %>
webpackビルドや起動方法などは先ほどと同じ。
なんか動いてるっぽい。
所感
今までwebpack絡めた環境作るのが手間に感じていたのが、webpacker使うとかなり楽に感じました。
いままではwebpackでビルド→ビルド生成物をasset pipelineに乗せてダイジェスト付与の恩恵だけ受ける、みたいなことをやってたんですが、そのあたりも含めて面倒見てくれるのは嬉しく思いました。
Rails 5.1に期待。