こんにちは。エンジニアの大久保です。年の瀬ギリギリにブログを書いてみました。
シンクロ・フードでは、半年くらい前からReactの導入を少しずつやっているのですが、今回はgulpが動作している非SPAサイトに対するReactビルド環境を紹介したいと思います。
「Reactを使ってみたいけれど、ゼロからプロジェクトを作る機会は少ない。だから稼働中のWebサイトに対してReactを使いたい。でもどのような環境にしているのだろう」という方向けに、一つの事例として参考にしていただければと思います。
結論から言うと、gulp+webpack+babelの組み合わせでReactのJSXをビルドし、JavaScriptは複数のエンドポイントに出力する、という方法を取っています。
尚、RailsでReactを使う場合は違う方法をとっているため、今回はあくまでもgulpでのビルドプロセスがある環境、且つSPAではないサイトにReactを導入する場合の事例です。
gulp+webpackでのビルド
弊社では、すでにgulpでのSassビルドを行なっていたため、gulp経由でReactをビルドしたいと思っていました。
gulp経由でReactをビルドする構成としては、以下の2つが候補に挙がるのではないでしょうか。
- gulp+browserify+babelify
- gulp+webpack+babel
弊社では両方とも設定してみた結果、設定としてスッキリする、という理由からwebpackを使ったほうに決めました。当初は、gulp→webpack、という、両方とも似たような役割のツールを重ねることが気持ち悪かったのですが、結果としては気にならなくなりました。
ただし、これは既にgulpを使った環境があるからこのような構成にしたのであって、gulpなどのタスクランナーを使っていないならば、webpackを直接使ってビルドすることをおすすめします。
具体的な導入手順
ディレクトリ構成
ディレクトリ構成は以下のような感じ。わかりやすいように単純化しています。
project ├── src │ └── main │ └── webapp │ ├── es2015-src │ ├── es2015-dest │ └── 省略... └── gulpfile.js
なんとなくJavaでのWebサイトを作った場合によくあるディレクトリ構成にしてみました。
上記例では、es2015-srcディレクトリにおいたjsファイルが、es2015-destに出力されることになります。
では、手順を紹介してみます。
パッケージのインストール
まずgulp-webpack
のインストール。
npm install --save-dev gulp-webpack
引き続き、babel関連のインストール。
npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react
更に、vinyl-named
を入れます。これは後ほど説明する、複数エンドポイントにjsを出力するために必要なパッケージです。
npm install --save-dev vinyl-named
これでビルドに必要なパッケージのインストールは完了です。
gulpfile.js
続いてgulpfile.jsを記載します。
var gulp = require('gulp'); var webpack = require('gulp-webpack'); var named = require('vinyl-named'); gulp.task('webpack', function () { return gulp.src('src/main/webapp/es2015-src/**/index.js') .pipe(named(function(file) { return file.relative.replace(/\.[^\.]+$/, ''); })) .pipe(webpack({ module: { loaders: [ { test: /\.js?$/, exclude: /(node_modules)/, loader: 'babel-loader', query: { presets: ['es2015', 'react'] } } ] } })) .pipe(gulp.dest('src/main/webapp/es2015-dest/')); }); // watchタスク gulp.task('watch', function () { gulp.watch('src/main/webapp/es2015-src/**/*.js', ['webpack']); }); gulp.task('default', ['webpack', 'watch']);
webpackという関数の中で渡しているオブジェクトがwebpackのオプションです。ここでbabelによるビルドと、presetsを指定することで、JSXをビルドすることができます。
次の項目で説明しますが、上記設定はindex.js、というファイル名のjsファイルだけをビルドするようにしています。それと、複数jsを書き出すための設定が加わっています。
以上で、Reactをビルドするための環境構築は完了です。
gulpfileに関する捕捉
複数jsの書き出しについて
SPAサイトでない場合、ページ毎に読み込むJSが違う、ということはよくあると思います。
弊社もそういったWebサイトを運営しており、webpackでもsrcに入れたjs毎に別々にビルドしたい、というニーズがありました。
jsファイルを追加するたびに、webpackのオプションを修正していけば個別出力は可能なのですが、毎回gulpfileをいじくるのも面倒だったので、src側においたjsの構造をそのままdest側に出力させる、ということをやっています。
そのために、vinyl-named
というパッケージを使って、gulpfileを都度修正することなく、複数jsを出力するようにしています。
ここについては、以下の方のエントリーが非常に参考になりました。
http://2no.hatenablog.com/entry/2015/06/08/170511
なぜindex.jsのみをビルドするか
Reactではimport/exportsを使ったJSを書くことが普通だと思うのですが、*.jsでビルド対象のjsファイルを指定すると、本来ビルド不要な、importされる側のjsも個別にビルドしてしまうため、src側でindex.jsのみをビルドするようにしています。
index.jsの場合はビルド対象、それ以外のファイル名はビルド除外、というルールでやっています。
これは運用でカバーという状態なので、改善が必要だと思っています。
まとめ
以上が弊社のgulpビルドをしている非SPAサイト向けReactビルド環境のご紹介でした。
シンクロ・フードではこのようなフロントエンドに対して興味を持つエンジニアを募集しています(フロントだけではありませんが!)。
興味を持った方がいらっしゃれば、お気軽にご応募ください!それでは!
http://www.synchro-food.co.jp/recruit/