同書の書評は「Reactビギナーズガイド」を読みました。」という同タイトルのブログを書いているので興味のある方はご覧ください。
今回の目標
今回の目標は「Reactビギナーズガイド」のサンプルアプリケーションをRailsに乗せて作る。
(React歴1.5ヶ月くらいなのでどうか温かい目で読んで頂けると...)
1. 開発準備
1-1. Railsアプリケーションの作成
バージョン: Ruby 2.4.0, Rails 5.0.1
rails new アプリケーション名
1-2. posts_controllerの作成
同書で作る「WhinePad」というアプリケーションは「ワインについてのメモや評価を記録できるアプリケーション」とのことですが、もう少し庶民的なアプリケーションにしたいので「BookPad」という「書籍についてのメモや評価を記録できるアプリケーション」に路線変更をしたいと思います。
ということで、Rails側では「books」という命名でコントローラを作成したいと思います。
rails g controller books index
とりあえずindex
アクションを作成しておきます。
1-3. package.jsonの作成
ReactやReact開発をする上で入れておきたいJavaScriptライブラリはnpmで管理したいのでpackage.jsonを用意します。
npm install --save ライブラリ名
とすることでインストールしたライブラリをpackage.jsonに書き込んでくれます。
こうしておけばpackege.jsonに書き忘れることはないし、アルファベット順で書き込んでくれpackage.jsonの見通しが良くなるため僕は大抵--save
オプションをつけるようにしています。
というわけで、まずは最低限必要な以下のライブラリをインストールしておきます。
- React
- ReactDOM
npm install --save react react-dom
node_modules
というディレクトリに大量のライブラリがインストールされるので、.gitignore
とかに指定しておきましょう。
1-4. React用のディレクトリを作成する
webpackを使った Rails上でのReact開発というクックパッドの開発者ブログを読むとapp
配下にclient
というディレクトリを作成しています。個人的にはclient
よりもfrontend
とかの方が直感的だと思ったのでfrontend
にしています。
2. HelloWorld
2-1. books.jsの作成
ここまでで準備は整ったので、Reactのコードを書き、HelloWorldを表示していきたいと思います。
Reactではコードのまとまりをコンポーネントという概念として表現しているのでapp/frontend
ディレクトリにbooks.js
というファイルを作成します。
2-2. Postsコンポーネントの作成
今回はECMAScriptを使ってJavaScriptを記述していきます。
import React from 'react'
class Books extends React.Component {
render() {
return (
<h1>HelloWorld</h1>
)
}
}
ECMAScriptではクラスを定義できるのでReact.Component
を継承したBooks
クラスを作成します。
コンポーネントの作成においては様々な書き方があるのでざっと見てみたい方はStateless な React Component の記法をまとめてみたなどを参照すると良いかと思われます。
また作成したコンポーネント内ではrender()
メソッドが記述されていますが、こちらはマストで記述する必要があり、逆にrender()
メソッドさえ記述されていれば最低限のReactコンポーネントとして成立します。このあたりについては「React コンポーネント ライフサイクル」などで検索すると概要が掴めるかと思います。
2-3. コンポーネントの描画
import React from 'react'
import ReactDOM from 'react-dom' // 追記
class Books extends React.Component {
render() {
return (
<h1>HelloWorld</h1>
)
}
}
// 以下を追記
ReactDOM.render(
React.createElement(Books),
document.getElementById("books")
)
React.createElement(Books)
という部分でPostsコンポーネントを元にDOM要素を作成し、document.getElementById("books")
という部分でpostsというid属性を持つHTMLにDOM要素を描画しています。
コンポーネントが描画されるapp/views/index.html.erb
にはbooks
というid属性を持つHTMLを記述していきます。
<div id='books'></div>
2-4. Babelのインストール
さて、描画するためのコードも書いたら後はJavaScriptをRailsに読み込ませるだけです。
しかしES6はまだ各ブラウザで対応されていなかったり、一部対応という状況なので現在のブラウザに対応する形に変換(トランスパイル)する必要があります。
同書ではトランスパイラとして「Babel」を使用しているのでそちらをインストールしていきます。ES6やBabelについてはES6の概要と、最新ブラウザに対応させる「Babel」の使い方などが参考になるかと思います。
npm install --global babel-cli
--global
オプションでグローバルにインストールすることで、システムのどこからでもbabelを使用できます。
2-5. JavaScriptのトランスパイル
babel --presets react,es2015 app/frontend -d app/frontend/build
最もシンプルなbabelのコマンドはbabel 変換したいファイル名 --out-file 変換後のファイル名
という形になりますが、今回はapp/frontend
ディレクトリにあるReactとes2015(ES6)のコードを丸ごとapp/frontend/build
ディレクトリにトランスパイルしています。
実際にトランスパイルしたファイルを開いてみると、15行程度で記述されていたReactのコードが44行程度のJavaScriptに変換されています。
2-6. Browserify
ES6のコードを変換してブラウザに対応させることができました。
あとはほぼRailsに読み込ませるだけと言っても過言ではないのですが、最後に問題となるのが依存関係です。
これまで書いたコードではReact.Component
を継承するためにファイル先頭でimport React from 'react'
というコードがあります。(同様にReactDOMも)トランスパイルしたファイルをRailsで読み込んでも、ここのimport
、つまり依存先が読み込めないのでコンポーネントの描画がうまくいきません。
そこで必要となるのがBrowserifyというライブラリです。
Browserifyはファイル内にrequire()という関数を見つけると、requireに指定してあるファイルを探し、依存関係を解決してくれます。
参考資料: Browserifyによる依存関係の解決
$ npm install --global browserify
$ browserify app/frontend/build/books.js -o public/assets/javascripts/bundle.js
babelによってimport
構文がrequire()
関数へと変換されているので、browserifyを実行すると依存関係を解決した状態で、bundle.jsというファイルへ書き出してくれます。
先ほどのトランスパイル済みのファイルは44行程度のJavaScriptだったのですが、browserifyで依存関係を解決した1つのファイルにまとめると数千行にも及ぶJavaScriptとなっていることが分かります。
2-7. Railsで読み込む
同書ではRailsについて一切触れられていないのでこの辺りのベストプラクティスがよく分かっていないのですが、とりあえず今回はpublic/assets/javascripts
ディレクトリにbundle.jsを作成したので、これを読み込みます。
views/layouts/application.html.erb
の</body>
の上に以下の1行を追加します。
<%= javascript_include_tag '/assets/javascripts/bundle.js' %>
<head></head>
内で読み込むと、<div id='books'></div>
の読み込みよりも先にjsが読まれ、Target container is not a DOM element.
というエラーが発生してしまいます。(解決策ご存知の方がいればご教授お願いします...)
さて、この時点でrails s
を実行するとlocalhost:3000/books/index
でHelloWorldと表示されるはずです。
今後の実装
とりあえずHelloWorldを表示させることができたら、React開発の基盤を準備することができたとみて問題ないでしょう。今後は「Reactビギナーズガイド」に沿ってコンポーネントを作成したり、データを取り扱った開発について投稿できればと思います。
Amazonでも買えます: Reactビギナーズガイド ―コンポーネントベースのフロントエンド開発入門