#はじめに
Reactを書いていると、Material UIを使うことも多いかと思います。
それをRails環境でも使用できたらと思い、実際にやってみました。
ReactをRailsで使う方法はいくつかありますが、今回はwebpackerを使用して動かしていきます。
まずwebpackerとは何なのか、全体像を掴んでから始める方がいいと思いますので、以下の記事をざっと読んでからスタートすると後々の理解が深まると思います。
webpack学習の基本のき
もし間違えている箇所があればご指摘をいただければ幸いです。
#環境
- Ruby 2.5.1
- Rails 6.0.2.2
- Yarn 1.22.4
- Node v12.16.1
#まずは環境構築(Rails / React / webpacker)
使用するディレクトリを作成し、そのディレクトリに移動します。
$ mkdir myapp
$ cd myapp
Gemfileの作成
$ bundle init
Writing new Gemfile to /myapp/Gemfile
Gemfileの中のrailsのコメントアウトを外します。
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
gem "rails"
コメントアウトができたら、bundle installでgemをインストールします。
$ bundle install --path vendor/bundle
このようにbundle install
だけでなく、--path
とパス指定を加えることで、そのアプリのディレクトリの中だけにインストールされます。
今回だとRailsアプリ(myapp)のルートディレクトリの下のvender/bundleディレクトリにインストールされます。
以下のような記載が出ればインストール完了です。
Bundle complete! 1 Gemfile dependency, 43 gems now installed.
Bundled gems are installed into `./vendor/bundle`
次に、以下のコマンドでwebpackerと同時にReactをインストールします。今回データベースはMySQLを使用したので末尾に--database=mysql
と記載します。
$ bundle exec rails new . --webpack=react --database=mysql
Gemfileを上書きする確認のメッセージが出るので、yを入力してEnterで先に進みます。
exist
identical README.md
identical Rakefile
identical .ruby-version
identical config.ru
identical .gitignore
conflict Gemfile
Overwrite /myapp/Gemfile? (enter "h" for help) [Ynaqdhm]
各種インストールが始まります。
Initialized empty Git repository in /Users/katakawaryouhei/Desktop/React/myapp/.git/
create package.json
create app
create app/assets/config/manifest.js
---略---
Bundle complete! 17 Gemfile dependencies, 74 gems now installed.
Bundled gems are installed into `./vendor/bundle`
---略---
✨ Done in 6.89s.
Webpacker successfully installed 🎉 🍰
rails webpacker:install:react
---略---
✨ Done in 6.34s.
Webpacker now supports react.js 🎉
Railsで必要なファイル、webpacker、Reactのインストールが完了しました。
Gemfileを確認すると、しっかりwebpackerもインストールできていることがわかります。
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3'
# Use mysql as the database for Active Record
gem 'mysql2', '>= 0.4.4'
# Use Puma as the app server
gem 'puma', '~> 4.1'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 4.0'
またこの時点でjsxファイルが生成されています。
import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
---略---
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<Hello name="React" />,
document.body.appendChild(document.createElement('div')),
)
})
#Railsの動作確認
次にパスワードを打ち込み、MySQLを立ち上げます。
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: <%= ENV['RAILS_DATABASE_USER'] %>
password: <%= ENV['RAILS_DATABASE_PASSWORD'] %>
host: localhost
今回パスワード等の機密情報の管理は、Dotenv-rails
というgemを使用して環境変数にしています。詳しくは以下の記事が参考になると思います。
[Ruby on Rails]環境変数の設定方法(.bash_profile、Dotenv-rails)
$ rails db:create
これでデータベースが立ち上がったので、Railsが動くか確認してみます。
$ bundle exec rails s
上記コマンド入力後、ブラウザのアドレス欄に localhost:3000 を入力します。
以下の画面が表示されればRailsが動作できています!
動作確認ができたのでRailsサーバーは、Ctrl + C で一旦停止します。
#React動作確認
まずはReactを表示するための画面を作りたいので、コントローラーとビューを作成します。
$ bundle exec rails g controller home index
create app/controllers/home_controller.rb
route get 'home/index'
invoke erb
create app/views/home
create app/views/home/index.html.erb
invoke test_unit
create test/controllers/home_controller_test.rb
invoke helper
create app/helpers/home_helper.rb
invoke test_unit
invoke assets
invoke scss
create app/assets/stylesheets/home.scss
ルーティングは以下のように変更します。
Rails.application.routes.draw do
root to 'home#index'
end
続いて、Reactを表示させる為に、以下のように記載しERBファイルでJSファイルを読み込みます。
<%= javascript_pack_tag 'application' %>
**javascript_pack_tag
**は、JavaScriptをapp/javascript/packs配下から読み込むwebpacker用のヘルパーメソッドです。
**'application'
はapp/javascript/packs/application.jsを示します。
他のファイルを指定したい場合は、javascript_pack_tag '他のファイル名'
と変更すれば、app/javascript/packs配下の別のファイルを読み込めます。
今回は'application'
**としました。application.jsを以下の1行を追加します。
require('./hello_react.jsx')
それでは準備ができたのでサーバーを起動していきます。
開発環境では、Rails用のサーバーとwebpack用のサーバーの両方の起動が必要になるので、コマンドも別のターミナルでそれぞれ打ち込む必要があります。
$ bundle exec rails s
$ bin/webpack-dev-server
これでも『Hello React!』の画面が立ち上がるかと思いますが、package.jsonを以下の様に書き加えると、
+ "scripts": {
"start": "bundle exec rails s & bin/webpack-dev-server"
},
以下のコマンド1回で済みます。
$ yarn start
上記コマンド入力後、ブラウザのアドレス欄に 再度localhost:3000 を入力します。
以下の画面が表示されればReactが動作できています!
#動作確認後のスタイル変更(Material UIの導入)
Reactの動作が確認できたので、
- CSSの反映
- Reactコンポーネント分割
- Rails上でMaterial UIの導入
までやっていきたいと思います。
まずはCSSを反映させたいので、以下のように変更を加えます。
<%= stylesheet_pack_tag 'application' %>
<%= javascript_pack_tag 'application' %>
先程の**javascript_pack_tag
に加えて、stylesheet_pack_tag 'application'
**を記載しました。
同じ要領で、application.jsに以下の1行を追加します。
require('./stylesheets/hello_react.css')
まだファイルを作っていないので、新しくフォルダとファイルを作成します。
後々使うファイルも全て作成してしまいます。
app/
└ javascript/
└ packs/
├ stylesheets/
│ └ hello_react.css
├ App.jsx
├ application.js
└ hello_react.jsx
具体的には、以下を新規で作成しました。
stylesheets/
stylesheets/hello_react.css
App.jsx
準備ができましたので、CSSファイルに記載を加えます。
body {
background-color: aqua;
}
わかりやすいように背景色を青色にしました。
これでリロードすると、CSSが反映されていることがわかります。
それでは、React側でコンポーネントを切り分けていきます。
下記コードのように各ファイルの記載を変更します。
import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
import App from './App'
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<App />,
document.body.appendChild(document.createElement('div')),
)
})
import React from 'react'
function App() {
return (
<div>
<h2>これはReactです。</h2>
</div>
)
}
export default App
わかりやすいように、Ruby側のファイルもERB記法で下記のように追記します。
<h2>これはRubyです。</h2>
<hr color="green">
<%= stylesheet_pack_tag 'application' %>
<%= javascript_pack_tag 'application' %>
これでリロードすると、ReactとRubyの両方で記載が完了していることがわかります。
最後に、Material UIを表示させていきます。
$ yarn add @material-ui/core
warning @material-ui/core > popper.js@1.16.1: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
---略---
├─ jss-plugin-nested@10.1.1
├─ jss-plugin-props-sort@10.1.1
├─ jss-plugin-rule-value-function@10.1.1
├─ jss-plugin-vendor-prefixer@10.1.1
├─ popper.js@1.16.1
└─ react-transition-group@4.4.1
✨ Done in 16.10s.
今回はCircle Progressを表示させてみるので、App.jsxを再度以下のように編集します。
import React from 'react'
import CircularProgress from '@material-ui/core/CircularProgress';
function App() {
return (
<div>
<h2>これはReactです。</h2>
<CircularProgress />
</div>
)
}
export default App
これでリロードすると、無事Material UIも表示できたかと思います!
##参考
https://github.com/rails/webpacker
https://www.playfulit.net/articles/2019/01/27/webpacker-react-frontend-on-ruby-on-rails/
https://free-engineer.hatenablog.com/entry/2018/04/26/165941