前回作成したhelloworldはブラウザでJSXTransformerを読み込みオンラインでjsにコンパイルしていました。実行時にChromeのデベロッパーツールに表示されるように、予めJSXはコンパイルすることが推奨されています。コンパイルの方法は、jsxコマンドを使う方法、 BrowserifyとReactifyを使う方法、最後にGulpのタスクでまとめる方法を順番に試してみます。
Getting Startedの復習
作成したhelloworld.jsxを少し修正してコンポーネントを作り構成してみます。ディレクトリ構成は以下です。
$ cd ~/react_apps/helloworld/
$ mkdir src dist
$ mv helloworld.jsx src/
$ tree .
.
|-- dist
|-- index.html
`-- src
`-- helloworld.jsx
Nameコンポーネントは作成時にプロパティを指定しています。nameプロパティは{this.props.name}
として参照できます。
var Name = React.createClass({
render: function() {
return (
<span>{this.props.name}</span>
);
}
});
var HelloWorld = React.createClass({
render: function() {
return (
<div>
<h1>Hello, world!</h1>
<Name name="Masato" />
</div>
);
}
});
React.render(
<HelloWorld />,
document.getElementById('example')
);
jsxファイルのパスも変更します。
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
<script src="http://fb.me/react-0.12.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
<script type="text/jsx" src="./src/helloworld.jsx"></script>
</head>
<body>
<div id="example"></div>
</body>
</html>
SimpleHTTPServerを起動します。
$ python -m SimpleHTTPServer 8080
Dockerコンテナで作業しているので、ngrokでトンネルします。
$ docker run -it --rm wizardapps/ngrok:latest ngrok 172.17.1.157:8080
ブラウザから確認します。ngrokのURLはランダムです。
http://684baaf0.ngrok.com
jsxコマンドを使う
Browserfyを使う前に、Getting Startedに書いてあるjsxコマンドを試してみます。react-toolsをnpmでインストールします。
$ npm install -g react-tools
jsxコマンドでsrcディレクトリにあるjsxファイルを、buildディレクトリにJavaScriptとしてコンパイルします。ファイルの拡張子をjsxにしているので、-xフラグの指定が必要です。
$ cd ~/react_apps/helloworld/
$ jsx -x jsx src/ dist/
built Module("helloworld")
["helloworld"]
jsファイルのロードをbodyに移動します。JSXTransformerも予めjsにコンパイルして不要になったので削除します。
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
<script src="http://fb.me/react-0.12.2.js"></script>
</head>
<body>
<div id="example"></div>
<script src="./dist/helloworld.js"></script>
</body>
</html>
ngrok経由でトンネルして、ブラウザで確認します。
http://684baaf0.ngrok.com/
BrowserifyとReactifyを使う
Browserifyブラウザ上でもNode.js用モジュールを使えるようにするライブラリです。ReactifyはJSX用のtransform moduleです。npmコマンドを使い、プロジェクトのディレクトリにBrowserify と Reactifyをインストールします。
$ cd ~/react_apps/helloworld
$ npm install react browserify reactify
jsxファイルでNode.jsと同じようにreactモジュールをrequireします。
var React = require('react');
var Name = React.createClass({
render: function() {
return (
<span>{this.props.name}</span>
);
}
});
var HelloWorld = React.createClass({
render: function() {
return (
<div>
<h1>Hello, world!</h1>
<Name name="Masato" />
</div>
);
}
});
React.render(
<HelloWorld />,
document.getElementById('example')
);
requireでモジュールを読み込んでいるので、index.htmlファイルからreact.jsのロードを削除します。
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<div id="example"></div>
<script src="./dist/helloworld.js"></script>
</body>
</html>
browserifyコマンドに-tフラグでreactifyモジュールを指定し、jsxファイルをjsにコンパイルします。生成されたhelloworld.jsをscript要素でロードすると、ブラウザでもNode.jsのモジュールが使えるようになります。コンパイルされたjsファイルはrequireしたreactモジュールもまとめて1つのファイルになっています。
$ browserify -t reactify src/helloworld.jsx > dist/helloworld.js
ngrok経由でトンネルして、ブラウザで確認します。
http://684baaf0.ngrok.com/
Gulpを使う
Gulpは手続き型で設定ファイルを記述する、タスクランナー&ビルドツールです。Gulpを使うため、少しリファクタリングします。
$ cd ~/react_apps/helloworld-gulp
$ tree .
.
|-- dist
|-- gulpfile.js
|-- index.html
`-- src
|-- main.js
`-- view.jsx
npmコマンドでGulpをグローバルにインストールします。
$ npm install -g gulp
npmコマンドでモジュールをローカルにインストールします。gulpはローカルのプロジェクトにインストールされたモジュールを使います。
$ npm install gulp react browserify reactify vinyl-source-stream
gulpfile.jsを作成します。reactifyでtransformしたjsファイルは、./dist/app.js
に出力されます。
var gulp = require('gulp');
var browserify = require('browserify');
var source = require("vinyl-source-stream");
var reactify = require('reactify');
gulp.task('browserify', function(){
var b = browserify({
entries: ['./src/main.js'],
transform: [reactify]
});
return b.bundle()
.pipe(source('app.js'))
.pipe(gulp.dest('./dist'));
});
helloworld.jsxファイルをリファクタリングして、main.jsとview.jsxファイルに分割します。
var React = require('react');
var view = require('./view.jsx');
React.renderComponent(
view(),
document.getElementById('content')
);
view.jsxは、HelloWorldコンポーネントをmodule.exports
に代入して公開して、main.jsから参照できるようにします。
var React = require('react');
var Name = React.createClass({
render: function() {
return (
<span>{this.props.name}</span>
);
}
});
var HelloWorld = React.createClass({
render: function() {
return (
<div>
<h1>Hello, world!</h1>
<Name name="Masato" />
</div>
);
}
});
module.exports = HelloWorld;
index.htmlでは、gulp browserify
タスクで1つにコンパイルした./dist/app.js
ファイルをロードします。
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<div id="content"></div>
<script src="./dist/app.js"></script>
</body>
</html>
gulp browserify
タスクを実行してJSXのコンパイルとrequireしたモジュールなどをまとめます。
$ gulp browserify
[13:47:57] Using gulpfile ~/react_apps/helloworld-gulp/gulpfile.js
[13:47:57] Starting 'browserify'...
[13:47:59] Finished 'browserify' after 2.03 s
ngrok経由でトンネルして、ブラウザで確認します。
http://684baaf0.ngrok.com/
package.jsonを作成する
新しい環境でも同じモジュールがインストールできるように、package.jsonを作成してプロジェクトの情報を記述しておきます。最初にマニュアルでインストールしたnode_modules
を削除します。
$ cd ~/react_apps/helloworld-gulp
$ rm -fr node_modules/
npm init
コマンドを実行して、対話的にpackage.jsonを作成します。GitHubのリポジトリも自動で入れてくるので、入力した値はauthorだけでpackage.jsonファイルを作成できました。
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
name: (helloworld-gulp)
version: (1.0.0)
description:
entry point:
test command:
git repository: (https://github.com/masato/helloworld-gulp.git)
keywords:
author: Masato Shimizu
license: (ISC)
About to write to /home/docker/react_apps/helloworld-gulp/package.json:
{
"name": "helloworld-gulp",
"version": "1.0.0",
"description": "",
"main": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/masato/helloworld-gulp.git"
},
"author": "Masato Shimizu",
"license": "ISC",
"bugs": {
"url": "https://github.com/masato/helloworld-gulp/issues"
},
"homepage": "https://github.com/masato/helloworld-gulp"
}
Is this ok? (yes) yes
前回は--save-dev
フラグを付けませんでしたが、package.jsonのdevDependenciesに設定が書かれるように、npm installするときは--save-dev
を忘れずつけます。
$ npm install --save-dev gulp react browserify reactify vinyl-source-stream
package.jsonを確認すると、devDependenciesが追加されました。
...
"devDependencies": {
"browserify": "^8.0.2",
"gulp": "^3.8.10",
"react": "^0.12.2",
"reactify": "^0.17.1",
"vinyl-source-stream": "^1.0.0"
}
}
package.jsonをリポジトリに追加して、GitHubにpushしておきます。
git cloneし直す
GitHubにpushしたリポジトリを別のディレクトリにcloneして動作確認をします。
$ cd ~/react_apps
$ git clone https://github.com/masato/helloworld-gulp.git gulp-test
プロジェクトのディレクトリに移動して、npm install
を実行してローカルにモジュールをインストールします。gulp browserify
タスクを実行してJSXファイルをコンパイルします。
$ cd gulp-test
$ npm install
$ gulp browserify
ローカルでSimpleHTTPServerを起動します。
$ python -m SimpleHTTPServer 8080
ブラウザから動作確認します。
http://684baaf0.ngrok.com/