7
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rails4系プロジェクトにReact + webpacker(css-modules)を導入する

Last updated at Posted at 2017-12-11

既存のRailsプロジェクトにReactとwebpackerを導入した時の手順をメモします。
(まだ本番運用はしてません)

環境

  • ruby 2.4.2
  • Rails 4.2.8
  • Mac OS 10.12.6
  • webpacker 3.0.2

必要なgemをインストール

Gemfile更新してbundle install

Gemfile
gem 'react-rails'
gem 'webpacker', '~> 3.0'

yarnが必要なのでインストールしておく。

$ brew install yarn
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core, homebrew/php).

...中略

Error: Xcode alone is not sufficient on Sierra.
Install the Command Line Tools:
  xcode-select --install

※xcodeまわりで怒られたら言われるがままにインストール。

$ xcode-select --install
xcode-select: note: install requested for command line developer tools

webpackerをインストール

railsのバージョンによってコマンドが異なるので注意。

bundle
bundle exec rails webpacker:install

# OR (on rails version < 5.0)
bundle exec rake webpacker:install

$ bundle exec rake webpacker:install
      create  config/webpacker.yml
Copying webpack core config and loaders
      create  config/webpack
      create  config/webpack/development.js
      create  config/webpack/environment.js
      create  config/webpack/production.js

...中略

├─ webpack-dev-middleware@1.12.2
├─ webpack-dev-server@2.9.5
├─ websocket-driver@0.7.0
├─ websocket-extensions@0.1.3
├─ yargs-parser@4.2.1
└─ yargs@6.6.0
warning No license field
✨  Done in 5.97s.
Webpacker successfully installed 🎉 🍰

さらにreact用にテンプレートをインストール。

$ bundle exec rake webpacker:install:react
Webpacker is installed 🎉 🍰

...中略

├─ ua-parser-js@0.7.17
└─ whatwg-fetch@2.0.3
warning No license field
✨  Done in 5.82s.
Webpacker now supports react.js 🎉

インストール成功 :clap:

Reactをインストール

例のごとくコマンド叩く。

$ rails generate react:install
Expected string default value for '--helper'; got false (boolean)
Expected string default value for '--assets'; got false (boolean)
Expected string default value for '--decorator'; got true (boolean)
Expected string default value for '--decorator'; got true (boolean)
Expected string default value for '--jbuilder'; got true (boolean)
      create  app/javascript/components
      create  app/javascript/components/.gitkeep
warning package.json: No license field
warning No license field
warning "@rails/webpacker > postcss-cssnext@3.0.2" has unmet peer dependency "caniuse-lite@^1.0.30000697".
warning " > webpack-dev-server@2.9.7" has unmet peer dependency "webpack@^2.2.0 || ^3.0.0".
warning "webpack-dev-server > webpack-dev-middleware@1.12.2" has unmet peer dependency "webpack@^1.0.0 || ^2.0.0 || ^3.0.0".
warning No license field
      append  app/javascript/packs/application.js
      create  app/javascript/packs/server_rendering.js

サンプルつくってみる。

$ rails g react:component HelloWorld greeting:string
      create  app/javascript/components/HelloWorld.js

以下のようなjsファイルが生成されるので、

app/javascript/components/HelloWorld.js
import React from "react"
import PropTypes from "prop-types"
class HelloWorld extends React.Component {
  render () {
    return (
      <div>
        <div>Greeting: {this.props.greeting}</div>
      </div>
    );
  }
}

HelloWorld.propTypes = {
  greeting: PropTypes.string
};
export default HelloWorld

viewから呼び出してみる。

まずはlayoutsでwebpackのファイルを読み込むようにして、

app/views/layouts/application.html.slim
...
= javascript_pack_tag 'application'
...

ヘルパで呼び出す。

app/views/hoge/index.html.slim
= react_component('HelloWorld', {greeting: 'Hello'})

/hoge/indexにアクセスすると、「Greeting: Hello」と表示された :sunglasses:

css-modulesを使う

webpack使ってるし、せっかくなのでcss-modules使ってみる。

スタイル作成してimportする。

app/javascript/components/HelloWorld.scss
.hoge {
  color: red;
}
app/javascript/components/HelloWorld.js
import React from "react"
import PropTypes from "prop-types"
+ import Style from './HelloWorld.scss'
class HelloWorld extends React.Component {
  render () {
    return (
      <div>
-         <div>Greeting: {this.props.greeting}</div>
+         <div className={Style.hoge}>Greeting: {this.props.greeting}</div>
      </div>
    );
  }
}

HelloWorld.propTypes = {
  greeting: PropTypes.string
};
export default HelloWorld

layoutsにも追記忘れずに。

app/views/layouts/application.html.slim
...
= stylesheet_pack_tag 'application'
...

css-modules使うためにloaderの設定方法を変更する。(css-loaderでmodules: trueにする。)

設定はdocsのとおりにした。
https://github.com/rails/webpacker/blob/master/docs/webpack.md#overriding-loader-options-in-webpack-3-for-css-modules-etc
※バージョンによって変わってくるので注意。以下はwebpacker 3.0.2の場合。

const { environment } = require('@rails/webpacker')
+ const merge = require('webpack-merge')
+ 
+ const myCssLoaderOptions = {
+   modules: true,
+   sourceMap: true,
+   localIdentName: '[name]__[local]___[hash:base64:5]'
+ }
+ 
+ const CSSLoader = environment.loaders.get('style').use.find(el => el.loader === 'css-loader')
+ 
+ CSSLoader.options = merge(CSSLoader.options, myCssLoaderOptions)

module.exports = environment

webpack-mergeが必要なのでnpmでインストールする。

$ npm install webpack-merge

bin/webpackコマンドでビルドする。

$ bin/webpack
Hash: d9e1c05fb0115c67db9a
Version: webpack 3.10.0
Time: 4415ms
                                                Asset       Size  Chunks                    Chunk Names
             server_rendering-2fc6d35ea1f628531946.js    1.96 MB       0  [emitted]  [big]  server_rendering
                  application-e4edca0d11e9022b85f8.js    1.96 MB       1  [emitted]  [big]  application
                  hello_react-2fa08b964a0fbb7ea3bf.js    1.68 MB       2  [emitted]  [big]  hello_react
     application-58ab649efbf1ea4787a749efd9c58636.css  419 bytes       1  [emitted]         application
server_rendering-58ab649efbf1ea4787a749efd9c58636.css  419 bytes       0  [emitted]         server_rendering
                                        manifest.json  380 bytes          [emitted]
  [28] ./app/javascript/components ^\.\/.*$ 236 bytes {0} {1} [built]
  [41] ./app/javascript/packs/application.js 730 bytes {1} [built]
  [42] ./app/javascript/packs/hello_react.jsx 739 bytes {2} [built]
  [43] ./app/javascript/packs/server_rendering.js 299 bytes {0} [built]
    + 44 hidden modules
Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/index.js??ref--5-2!node_modules/postcss-loader/lib/index.js??ref--5-3!node_modules/resolve-url-loader/index.js!node_modules/sass-loader/lib/loader.js??ref--5-5!app/javascript/components/HelloWorld.scss:
       2 modules

ビルドできた :clap:

/hoge/indexにアクセスすると、「Greeting: Hello」が赤文字で表示された :sunglasses:

Macのローカルでの作業はいったんここまで。
次はCIでの設定とかまとめていこうかな :bulb:

参考

7
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?