Reactを使おうとすると、ファイルの変換やらなんやら色々あるので、まずは簡単なsampleを使って各種開発環境を整えてみる。
#前提
npmを利用
ブラウザはchrome
最終的につくるのはこれ(http://todomvc.com/examples/react/#/)
#目次
- sampleページの作成
- webサーバの導入
- サーバーサイドでの変換
- browserifyの導入
- ファイル変更の監視とgulpジョブ
- sassの導入
までを行う。
続きは実装編へ
簡単なsampleページ
単体で動作する簡単なsample。
<html>
<head>
<script src="http://fb.me/react-with-addons-0.12.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
</head>
<body>
<div id="todo-app"></div>
<script type="text/jsx">
React.render(
<h1>Sample</h1>,
document.getElementById('todo-app')
);
</script>
</body>
</html>
scriptを切り出す
htmlにscriptを全て書いていくわけには行かないので、まずはsrc/app.jsへ切り出す
*JSXTransformerがajax通信を行う。chromeだとXHRでfile://へのアクセスができない(same origin policy)のでこのままだとエラーが発生する
webサーバーの導入
webサーバーを起動してアクセスする。
npm instal http-server -save
$(npm bin)/http-server
npm scriptを利用してwebサーバーの起動を簡単に
package.jsonにスクリプトを記述して起動する
"scripts": {
+ "start": "http-server",
"test": "echo \"Error: no test specified\" && exit 1"
},
npm start
jsxのサーバーサイドでの変換
jsxを毎回クライアントサイドで変換するのは当然速度的にNG。サーバーサイドでjsxをjavascriptに変換する。
(ただし、実際にはbrowserifyの導入後、以下のjsxコマンドは不要になる)
react-toolsの導入
npm install react-tools -save-dev
jsxコマンドの実行で、jsx => javascriptへ変換
$(npm bin)/jsx --harmony src/ build/
watchさせる場合は、
$(npm bin)/jsx --harmony --watch src/ build/
合わせてhtmlを修正。text/jsxではなくtext/javascriptになる
<html>
<head>
<script src="http://fb.me/react-with-addons-0.12.2.js"></script>
- <script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
</head>
<body>
<div id="todo-app"></div>
- <script type="text/jsx" src="src/app.js">
+ <script type="text/javascript" src="build/app.js">
</script>
</body>
</html>
browserifyの導入
reactJsでは、pluginの導入を含めてcommonJS形式で依存性の解決をすると便利なようのようなので、browserifyを導入する。
browserifyは基本的にjavascriptファイルの変換を行う。jsx記法はそのままでは変換できないため、ここではまずjsxコマンドで変換したjavascriptファイルをターゲットとして依存性の解決のみ行う。
別のスクリプトファイルを作成し、app.jsで利用する
依存性解決のサンプルとして、新しいスクリプトファイルを作成してapp.jsで読み込む実装をしてみる。
var util = function(){
console.log('util');
}
module.exports = util;
var util = require('./util.js')
React.render(
<h1>TODO</h1>,
document.getElementById('todo-app')
);
util();
browserifyのinstall
npm install browserify -save-dev
build/app.jsをbrowerifyで変換
$(npm bin)/browserify build/app.js -o build/bundle.js
<div id="todo-app"></div>
- <script type="text/javascript" src="build/app.js">
+ <script type="text/javascript" src="build/bundle.js">
</script>
</body>
ここまででは、
- jsxコマンドでsrc/app.js => build/app.js
- browserifyコマンドでbuild/app.js => build/bundle.js
の二つの変換を行った。
reactifyの導入
reactifyは、browserifyのtransform module。jsxファイルをjavascriptへ変換してくれる。これによって、JSX => javascript(commonJS) => javascriptという変換が行われる。
reactifyの導入
npm install reactify -save-dev
src/app.jsを指定して直接変換
$(npm bin)/browserify -t reactify src/app.js -o build/bundle.js
htmlは以下のまま変更無し
<html>
<head>
<script src="http://fb.me/react-with-addons-0.12.2.js"></script>
</head>
<body>
<div id="todo-app"></div>
<script type="text/javascript" src="build/bundle.js">
</script>
</body>
</html>
react.jsをbrowserifyで解決する。
htmlに直接書いたreact-with-addons-0.12.2.jsをcommonJS形式で記述し、browserifyで依存性を解決する
<head>
- <script src="http://fb.me/react-with-addons-0.12.2.js"></script>
</head>
+ var React = require('react/addons');
var util = require('./util.js');
reactの導入
npm install react -save
browserifyを再実行
$(npm bin)/browserify -t reactify src/app.js -o build/bundle.js
変更の監視
依存しているファイルの変更を監視するwatchifyを導入する
watchfyの導入
npm install watchify --save-dev
watchifyを実行
$(npm bin)/watchify -t reactify src/app.js -o build/bundle.js -v
src/util.jsやapp.jsの変更を監視し、自動でファイルの変換が行われる。
変更を監視するジョブの作成
npm install gulp --save-dev
npm install vinyl-source-stream --save-dev
npm install gulp-duration --save-dev
npm install gulp-util --save-dev
var gulp = require('gulp');
var browserify = require('browserify');
var reactify = require('reactify');
var watchify = require('watchify');
var source = require('vinyl-source-stream');
var duration = require('gulp-duration');
var gulpUtil = require('gulp-util');
var buildScript = function(watch){
var bundler = browserify(['./src/app.js'],{
cache:{},
packageCache:{},
verbose:true,
debug:true
});
if(watch){
bundler = watchify(bundler);
}
bundler.transform(reactify);
var rebundle = function(){
gulpUtil.log('start bundle');
return bundler.bundle()
.on('error',function(err){
console.log(err.message);
this.emit('end');
})
.pipe(source('bundle.js'))
.pipe(duration('rebuilding files'))
.pipe(gulp.dest('./build/'));
}
bundler.on('update',rebundle);
return rebundle();
}
gulp.task('build:script', function() {
return buildScript(false);
});
gulp.task('watch:script', function() {
return buildScript(true);
});
gulp build
gulp watch
で実行を確認
sassの導入
最後に、、sassでスタイルを記述するため、sassのbuildと監視タスクを作成する
npm install gulp-sass --save-dev
sassの変換と、watchタスクの追加。
var sass = require('gulp-sass');
gulp.task('build:sass', function () {
gulp.src('./src/sass/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'));
});
gulp.task('build',['build:script','build:sass']);
gulp.task('watch',['watch:script','build:sass'],function(){
gulp.watch( './src/sass/**/*.scss', ['build:sass'] );
});
sassの導入に伴い、ファイル構成を少し変更する。
index.html
src
├js
│ └app.js
└sass
└main.scss
#ソースコード
今のところこんな感じになってるはず
https://github.com/haradakunihiko/react-todo-tutorial/tree/v0.1
#参考
##browserify
https://github.com/substack/node-browserify#usage
https://github.com/substack/browserify-handbook#node-packaged-manuscript
##watchify
https://github.com/substack/watchify
##gulpfile/build
http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/
https://github.com/gulpjs/gulp/blob/master/docs/recipes/fast-browserify-builds-with-watchify.md
https://gist.github.com/Sigmus/9253068