Table of Contents
私は今HPEのFort Collinsオフィスに居候している。 HPEは最近、Reactを使ったUXフレームワークであるGrommetを開発していて、私が扱っている製品もそれを使う兆しが見えてきた。 Grommetはいずれ仕事で触ることになりそうなので、まずはReactの勉強をと思い、とあるAtomパッケージの開発に敢えて使ってみた。
このエントリには、その作業の中で得た知識などについて書いた。 ただし、Reactを使った開発のノウハウみたいなものまでは得ていないので書いていない。
(因みにGrommetはGitHubで公開されているが、ほとんど話題になっておらずスターも現時点で245しかついていない。。。)
Reactとは
ReactはFacebookが開発しているWeb UIのフレームワークで、MVCのVだけを実装したもの。 2013年に最初のバージョンが公開され、世界中で流行ってきているらしい。
その特徴(というかほぼ全容)は仮想DOM(Virtual DOM)。 ReactのAPIを使うと、リアルDOMと一対一で対応する仮想DOMのツリーを作ることができ、UIを組み立てられる。 リアルDOMの構築や更新はReactが最適化された方法でやってくれるので、性能がいいUIができるらしい。 因みに、仮想DOM自体はReact特有の技術ではなく、別の実装もある。
もう一つの特徴はJSX。 これは、JavaScriptのコードの中で、XMLみたいな構文で仮想DOMを記述するための拡張構文。 これを使うとReactコードが見やすく簡単に書けるけど、当然普通のJavaScript実行環境では動かないので、プリコンパイルなどが必要になる。
FacebookはReactを使った開発にFluxというアーキテクチャの採用を推奨している。 FluxはMVCアーキテクチャに置き換わるもので、従来の複雑なデータフローに反発し、一方向のシンプルなデータフローを提供する。 Fluxは単なるアーキテクチャで、その全体の実装を支援するフレームワークは現時点では無い。 (多分。Relayが一部支援してくれるっぽい。)
Reactを触った感想
Reactは本当にちょっとしか触っていないので、あまりよく分かっていないんだろうけど、なんだか使いにくかった。
Reactは仮想DOMを作るところしか助けてくれないので、他のことは全部自分でやらないといけない。 FacebookはReact用のウィジェットすら提供していない。 昔仕事で全部入りのDojoを使っていたので、それとのギャップをすごい感じた。
そのうえ、他のフレームワークやライブラリと組み合わせて使おうとすると仮想DOMが壁になってくる。普通のフレームワークはリアルDOMを扱うからだ。 例えば、JavaScriptを書いているとすぐjQueryを使いたくなるが、これでリアルDOMを直接いじってしまってはReactを使う意味がない気がする。
AtomパッケージでReactを使う
Reactはnpmでも提供されていて、Atomパッケージの開発に簡単に使える。
パッケージのpackage.json
のdependencies
にreactとreact-domを入れておけば、パッケージコード中で以下の様に仮想DOMを作れるようになる。
var React = require('react');
var ReactDOM = require('react-dom');
class MyComponent extends React.Component {
render() {
return <div>Hello World</div>;
}
}
ReactDOM.render(<MyComponent />, node);
BabelによるJSXの手動コンパイル
JSXのコンパイルにはBabelを使うのがいい。 手動コンパイルにはBabelのコマンドラインツールが必要で、これはnpmで提供されている。 npmコマンドはAtomに同梱されているので別途インストールは不要。
以下が手順の詳細。
Babelのコマンドラインツールのインストール
任意の場所で、
# npm install -g babel-cli
を実行すると、Babelのコマンドラインツールがグローバルにインストールされ、任意の場所で
babel
コマンドが使えるようになる。Babelの定義ファイル作成
適当なフォルダ(プロジェクトのルートなど)に
.babelrc
というBabelの定義ファイルを作り、以下を書いておく。{ "presets": ["react"] }
Reactプラグインのインストール
.babelrc
に書いたpresets
の値は、コンパイルにReactプラグインを使うという意味。 なので、以下のコマンドでReactプラグインを(ローカルに)インストールする必要がある。# cd <.babelrcを置いたフォルダ> # npm install babel-preset-react
コンパイル
babel
コマンドでコンパイルを実行する。例えば以下を実行すると、# cd <.babelrcを置いたフォルダ> # babel src -d lib
src/*.jsx
がコンパイルされて、lib/*.js
に出力される。
language-babelパッケージによるJSXの自動コンパイル
上記Babelによるコンパイルは、Atomならlanguage-babelパッケージで自動化できる。
以下、Atomパッケージの開発でlanguage-babelを利用する手順を書く。
language-babelのインストール
language-babelをAtomのSettingsなどからインストールして、language-babelのSettingsで、
Allow Local Override
にチェックを付ける。Babelの定義ファイル作成
手動のと同じ内容の
.babelrc
をパッケージプロジェクトのルートに置く。package.json編集
パッケージプロジェクトの
package.json
のdependencies
の下あたりに以下の定義を追加して、BabelとReactプラグインへの依存を張る。"devDependencies": { "babel-core": "^6.1.2", "babel-preset-react": "^6.1.2" }
上記定義を追加したら、
apm install
を実行して追加した依存をダウンロードする。因みに、
devDependencies
はdependencies
と似てるけど、開発時だけに必要なモジュールを定義するプロパティ。devDependencies
に書いたものはapm install
したときはダウンロードされるけど、パブリッシュされたものをインストールするときにはダウンロードされない。language-babelの設定ファイル作成
language-babelの設定は
.languagebabel
というファイルにかく。 これに以下の様な内容を書いてパッケージプロジェクトのルートに置く。{ "babelMapsPath": "lib", "babelMapsAddUrl": false, "babelSourcePath": "src", "babelTranspilePath": "lib", "createMap": false, "createTargetDirectories": true, "createTranspiledCode": true, "disableWhenNoBabelrcFileInPath": false, "suppressSourcePathMessages": true, "suppressTranspileOnSaveMessages": false, "transpileOnSave": true }
これで、
<パッケージプロジェクトのルート>/src/*.jsx
が、Atomで編集して保存したときにコンパイルされ、<パッケージプロジェクトのルート>/lib/*.js
に出力されるようになった。
BabelでJSXをコンパイルする場合の制限
手動にしろ自動にしろ、JSXのコンパイルにBabelを使う場合、BabelがCoffeeScriptに対応していないので、CoffeeScript + JSXでは書けない。 JavaScript + JSXで書かないといけない。
Minified exception
React周りでバグを作りこんでエラーが発生した場合、コンソールに以下のようなエラーメッセージが出ることがある。
Uncaught Error: Minified exception occured; use the non-minified dev environment for the full error message and additional helpful warnings.
これではエラーの詳細はわからない。詳細を見たい場合は、AtomをDev Modeで開いておく必要がある。 (e.g. Atomのメニューバーの[View]>[Developer]>[Open In Dev Mode]から開く。)