React(JSX)開発にBrowserifyとReactifyを導入
そろそろ <script>
タグではなく、Node.jsらしく require
でモジュール読み込みしたくなってきたので、Browserifyを試してみることにしました。
ベースとしたプロジェクト
以前React on NW.jsの取っ掛かりとして作ったサンプル があったので、違いを理解するためにも、それをベースにして組み込んでみることにしました。
主要なソースだけ抜き出すと、 index.html と app.jsx の2つで、以下のような単純なものです。
index.html
<html> <head> <title>React on NW.js</title> <script src="node_modules/react/dist/react.js"></script> </head> <body> <div id="app"></div> <script src="build/app.js"></script> </body> </html>
app.jsx
'use strict'; (function() { var Hello = React.createClass({ render: function() { return ( <h1>Hello, {this.props.name} !</h1> ); } }); React.render( <Hello name='React Component' />, document.getElementById('app') ); })();
Browserifyを使ってみる
CommonJS形式のNode.js向けパッケージをブラウザ向けのJSでも読み込めるようにする、つまり require
を使えるようにするためのツール。
概要を把握するのは、こちら( browserify をはじめてみる - Please Sleep )の記事がわかりやすかったです。
本来なら上記記事でも紹介されているように、GruntやGulpなどのタスクランナーと組み合わせていくのが良いと思われますが、まずは動作を理解するために単独で使うようにしてみました。
インストール
npmからインストール。
依存関係をpackage.jsonに残せるように、 --save-dev
を付けています。
$ npm install browserify --save-dev
コードを変更
サンプルをベースに、 require
を使ったものに書き換えてみました。
まずは app.jsx からHelloコンポーネント部分を切り出し、単独の Hello.jsx とします。
require
で読み込めるように、 module.exports
を追加しました。
Hello.jsx
'use strict'; var Hello = React.createClass({ render: function() { return ( <h1>Hello, {this.props.name} World !</h1> ); } }); module.exports = Hello;
切り出し元の app.jsx には、切り出したHelloコンポーネントを読み込む require
を追加します。
app.jsx
'use strict'; (function() { var Hello = require('./Hello'); React.render( <Hello name='React Component' />, document.getElementById('app') ); })();
index.html で、JSXから変換した app.js を読み込んでいた <script>
タグを、 Browserifyで変換後のJavaScriptとする bundle.js へ書き換えます。
index.html
<html> <head> <title>React on NW.js</title> <script src="node_modules/react/dist/react.js"></script> </head> <body> <div id="app"></div> <script src="build/bundle.js"></script> </body> </html>
Browserifyを実行
Browserify単独ではJSXの変換はできないため、まずはこれまで同様react-toolsでJSXをビルド後、Browserifyを実行します。
$ npm run build # `jsx ./src ./build --extension jsx` $ $(npm bin)/browserify build/app.js -o build/bundle.js
生成された bundle.js は、app.js および、 require
で読み込まれる先となる Hello.js が結合されたようなものになっていました。
先の index.html の修正で、この bundle.js を読み込むようにしていたため、 npm start (nw)
で実行すれば、動作が確認できました。
余談:Browserifyで指定するファイル
Browserifyで入力するファイルは、エントリポイントとなる app.js のみで良いのですが、最初それがわからずに、必要な.jsをすべて指定するのだと思って、
$ $(npm bin)/browserify build/*.js -o build/bundle.js
のように、 build/*.js
と実行していたところ、Helloコンポーネントが読み込まれないという状態になっていました。。。
Reactifyを組み合わせてみる
Browserifyの動作としては、複数のJavaScriptを1つのJavaScriptファイルへまとめるというもののようですが、Reactで開発をする場合、元のソースはJSX形式になります。
つまり、
JSX -> JavaScript -> Browserify
のように、JSXをJavaScriptへ変換後、変換したJavaScriptをBrowserifyでまとめる、というような流れになります。
先のように、react-toolsの jsx
コマンドを実行後、Browserifyを実行するようなワンライナー的なものを書いても良いのですが、ReactifyというBrowserify用のJSX変換プラグインがあるようなので、これを使うことにします。
BrowserifyのGitHubリポジトリには、変換プラグインの一覧( list of transforms · substack/node-browserify Wiki )が掲載されていました。
インストール
こちらも --save-dev
を付けて、npmからインストール。
$ npm install reactify --save-dev
コードを修正
このまま、よくあるサンプルのようにBrowserifyのオプションにReactifyを指定すれば動くと思ったのですが、少し修正が必要でした。
Helloコンポーネントを読み込んでいる require
の指定に、 .jsx
をつけておく必要があり、これがないと、コンポーネントが見つからないというエラーが発生します。
'use strict'; (function() { var Hello = require('./Hello.jsx'); // .jsxが必要 React.render( <Hello name='React Component' />, document.getElementById('app') ); })();
実行してみる
-t
オプションで、変換用のプラグインとなるReactifyを指定します。
$ $(npm bin)/browserify -t reactify src/app.jsx -o build/bundle.js
生成されたbundle.jsで実行したところ、問題なく動いてくれました。
まとめ
Browserify + Reactifyが動けば、これまで使っていたreact-toolsは不要ですね。
Web系の開発に便利なプラグインが色々とあるようなので、Browserify自体ももう少し研究してたいと思います。
参考
- browserify をはじめてみる - Please Sleep
- reactjs - React入門 - Part2: Browserify/Reactify/Gulpを使う - Qiita
- npm, browserify(reactify)をつかって、reactの開発環境を整える(jsxを事前に変換するようにする) - きたけーの朝は早いブログ
- Browserify
- substack/node-browserify
- list of transforms · substack/node-browserify Wiki
- andreypopp/reactify
- umi-uyura/react-on-nwjs-sample
実践Node.js プログラミング (Programmer's SELECTION)
- 作者: Mike Cantelon,Marc Harter,T.J. Holowaychuk,Nathan Rajlich,生越昌己,吉川邦夫
- 出版社/メーカー: 翔泳社
- 発売日: 2014/06/10
- メディア: 大型本
- この商品を含むブログ (1件) を見る