社内 React(flux)勉強会のために、シンプルなReact開発環境を作ったので公開します。
https://github.com/kjugk/flux_boilerplate
基本的な部分をこの記事で解説しますので、これからReact始めたいけど設定が面倒くさそう・・という方は是非お試しください!(フィードバック大歓迎です。)
前提
- node v5.3.0 で動作確認済
ディレクトリ構成
ディレクトリ構成は以下になります。(とりあえずReact に慣れることが目的なので、test や css は省略しています。)
2016/03/27 追記
JestでReact Component をテストする記事を作成しましたので、合わせてご参照ください!
http://qiita.com/kjugk/items/d0306eb2a1ff97a07d6f
追記ここまで
.
├── .babelrc
├── dist //browserify でコンパイルされた bundle.js ファイルを配置する。
├── gulpfile.js
├── index.html
├── js // JavaScript ファイルを配置する
│ └── index.js
│ └── 〜
│
├── node_modules
└── package.json
ビルドのフロー
##各ファイルの説明
gulpfile.js
gulp task を記述します。
jsタスクでは、js ディレクトリ配下のファイルを browserify で bundle.js ファイルにまとめて、dist ディレクトリに配置しています。
''use strict';
var gulp = require('gulp');
var gutil = require('gulp-util');
var browserify = require('browserify');
var watchify = require('watchify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var sourcemaps = require('gulp-sourcemaps');
var b = browserify({
entries: ['./js/index.js'],
transform: ['babelify'],
cache: {},
packageCache: {},
plugin: [watchify]
})
.on('update', bundle)
.on('log', gutil.log)
function bundle(){
return b.bundle()
.on('error', gutil.log.bind(gutil, 'Browserify Error') )
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./dist'));
}
gulp.task('js', bundle);
gulp.task('default', ['js']);
ここで重要なのは、browserify を設定している以下の記述です。
var b = browserify({
entries: ['./js/index.js'],
transform: ['babelify'],
cache: {},
packageCache: {},
plugin: [watchify]
})
.on('update', bundle) //ソース更新時に bundle を再実行
.on('log', gutil.log) //標準出力にログを書き出す
- transform に babelify を指定しています。b.bundle 関数実行時に、babelify によるES6, JSX のtranspile が実行されます。
- plugin に watchify を指定しています。b.bundle 関数実行時に watchify によるソースの監視が始まり、ソースを更新するたびに差分build が実行されます。
.babelrc
- babelify モジュール の設定はここに記述します。
{
"presets": ["es2015", "react"],
"plugins": ["transform-object-assign"]
}
-
ES6 と JSX をコンパイルするために、es2015 と react presets(基本的なpluginのセット) を定義しています。
-
React 開発でよく利用する、Object.assign() を有効にするため、transform-object-assign plugin を定義しています。
-
その他の babel の plugin は こちら
index.html
では、以下のように、script タグで コンパイル済みのbundle.js を読み込んでいるだけです。
~
<body>
<div id="root"></div>
<script src="dist/bundle.js"></script>
</body>
~
index.js
browserify のエントリーポイントになるファイルです。
以下のように、index.html の DOM に React Component をマウントしています。
前述のbabelify の 設定により、以下全ての js ファイルで、import 構文や JSX の記述が使えます。
import React from 'react'
import {render} from 'react-dom'
import ExampleApp from './components/ExampleApp'
render(
<ExampleApp />,
document.getElementById('root')
)
build
以上の設定により、コンソール から gulp コマンドを叩くと、ソースのコンパイル + 監視が始まります。(global に gulp をインストールしている場合は、gulp コマンドでOKです。)
$ node ./node_modules/gulp/bin/gulp
[15:31:10] Using gulpfile ~/flux_boilerplate/gulpfile.js
[15:31:10] Starting 'js'...
[15:31:12] 690771 bytes written (2.48 seconds)
buildが失敗すると、以下のようなエラー(一部dir name改変)がコンソールに吐き出されます。
[15:36:01] Browserify Error { [SyntaxError: /xxx/flux_boilerplate/js/components/ExampleApp.js: Adjacent JSX elements must be wrapped in an enclosing tag (33:6) while parsing file: /xxx/flux_boilerplate/js/components/ExampleApp.js]
pos: 675,
loc: Position { line: 33, column: 6 },
_babel: true,
どうやら Example.js ファイルの33行目のJSX が、タグで閉じられていないことが原因のようです。
修正してファイルを更新すれば、自動的にコンパイルが始まりるので、エラーが出なくなるまでコードを修正していきます。
動作確認
ブラウザで index.html を開くと、bundle.js が実行されます。
以上長々と説明してきましたが、ここまでできればあとは作って壊して、React に慣れるだけです!
ちなみに、Redux などを導入したい場合でも、基本的に上記の設定を流用できますので、試してみてください。
今後の課題
- error メッセージをもっと綺麗に出力したい。
- test を書く。=> http://qiita.com/kjugk/items/d0306eb2a1ff97a07d6f
- production 用のbuild task を定義する。
- rails と 組み合わせるbest practiceを探す。