p5js : Gulp + Browserify + Babel で p5を使えるテンプレート
p5.jsがWEBGL対応し、Javascriptでできる表現の幅が広がりそうです。
本家プロジェクトではEditorとかいろいろアプリのScaffolding的なものも用意されているのですが、いわゆるフロントエンド系の環境にならって個人でアプリプロジェクトのテンプレを作ってみました。
gulpによる自動化
下記のように、npm スクリプトによるJavascriptのビルドなども例としてはあるのですが、今回はgulpで自動化タスクを記述しました。
maxmechanic/simple-p5js-browserify · GitHub
タスクにしておいたほうが取り回しがいいのと、後々拡張しやすいと思ったので。 Gruntでもいいのですが、せっかくなのでgulpにしてみました。
あとp5.jsのbowerによる配信は非公式かつ、requireでの解決ができません。 npmならモジュールなので、requireで読み込むことができます。ES6のモジュールベースで作るプロジェクトと相性がよいのでnpmの配信を使います。
gulpfileは下記で公開されているものがよかったので、ベースにしました。
まずはuglify
、source map
などを入れてJavascriptビルドを盛りつつ、いらないタスクを削ります。
Babel
続いて本命のBabelです。
Processingは作りとしてはOpenGL的な命令セットで、明示的にオブジェクト指向のようなパラダイムをもっていませんが、言語としてはサポートしているのでコードが大きくなってくるとやはりオブジェクト設計をしたくなります。そしてファイルも分割したいと。
JavascriptではCommonJS、AMDなど歴史的にいくつかのモジュール構文が存在しますが、今後の筆頭はやはりES6だろうということでBabelを利用してこれを実現していきます。
最初は普通にglup-babel
でES5に変換してみたのですが、nodeのつもりでCommonJSのrequire構文に変換されるためフロントエンド環境では動きません。
gulp.task('js', function() { return gulp.src(config.js.files) .pipe($.babel({ presets: ['es2015'] })) .pipe(gulp.dest(config.js.output.directory)); });
ブラウザでBabelによる変換後のコードを動かすためにBrowserifyと合わせてビルドする必要があるのですが、babelify
の方が一緒にタスク化しやすかったので、
今回はbabelify
を利用します。
Browserify + Babelify
必要なモジュールをインストール。
$ npm install --save-dev browserify babelify babel-preset-es2015
変換は下記のワンライナーで実行できます。
var bundler = browserify('./app/js/appljs').transform('babelify', { presets: ["es2015"]} );
この結果のままだとgulpでpipeできないので、gulpのstreamで扱えるようにしてpipeできるようにします。
いくつか方法があったので、メモしておきます。今回作成したテンプレートでは①を使っています。
① vinyl-source-stream, vinyl-bufferを利用する
gulp.task('js', function() { var bundler = browserify('./app/js/app.js').transform('babelify', {presets: ["es2015"]}); return bundler.bundle() .on('error', function(error) {console.log(error);}) .pipe(source('app.js')) .pipe(buffer()) .pipe(gulp.dest('./dist/js2')); });
(参考) gulp & browserify (+watchify +babelify) · GitHub
② vinyl-transformを利用する(動作しない)
gulp.task('js', function() { var browserified = transform(function(filename) { var b = browserify(filename); b.transform('babelify', { presets: ["es2015"]}); return b.bundle(); }); return gulp.src('./app/js/app.js') .pipe(browserified) .pipe(gulp.dest('./dist')); });
(参考) Gulp+Browserifyでsrc/**/*.jsをdist/**/*.jsにする | 高橋文樹.com
しかしvinyl-transform
を利用したコードは、下記にあるように現在の最新(1.0.0)だと動きません。
③ through2を利用する
vinyl-transform
が動作しないissueで言及されていますが、下記にあるようにthrough2
を使って書き直す方法もあります。
gulp.task('js', function() { return gulp.src('./app/js/app.js') .pipe(through2.obj(function (file, enc, next){ console.log('browserify: ' + file.path); browserify(file.path) .transform('babelify', {presets: ["es2015"]}) .bundle(function(err, res){ // assumes file.contents is a Buffer if (err) {console.log(err);} file.contents = res; next(null, file); }); })) .pipe(gulp.dest('./dist')); });
(参考) exception: browserify + vinyl-transform · Issue #1198 · substack/node-browserify · GitHub
まとめ
というわけで、JSのビルドができました。後はeslintがes2015に対応するようにしたり、p5.jsモジュールでサンプルを実装したりと細々作業を行って…完成!
できたテンプレートはこちらになります。