Gulp+src/**/*.dist/**/*.

この投稿は2年半前の記事です。 情報が古くなっている可能性があるので、その点ご了承ください。
2015 年 4 月 6 日 780日前)
4,420文字 (読了時間11分)

SPONSORED LINK

どうでもいい話ですが、けっこうはまったので。

最近のWebフロントエンド開発ではタスクランナー系の話題がわりと多く、僕もgruntからgulpに乗り換えて数ヶ月という感じなのですが、Browserifyを触っておいた方がいいのかなと思い、直近の趣味プロジェクトで採用してみました。

Browserifyってなに?

そもそもなのですが、Browserifyというのはnodeのrequire('hogehoe')っていう依存関係解決機能をブラウザにも持ち込もうという試みですね。

たとえばjQueryなんかでいうと、こんな感じになります。

$ = require('jquery');

$(document).ready(function(){
    // 何かする
});

requireを実行したところにjQueryが読み込まれ、以降のダラー関数が有効になります。

このrequireなのですが、元々はnodeのインクルード機能なので、独特のお作法があります。Browserifyの公式ページにはこんな感じのサンプルが載っているのですが……

var unique = require('uniq');
var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];
console.log(unique(data));

このuniqというモジュールがどう書かれているかはともかく、普通のWebで使うJSとちょっと違うのは、requireした返り値を利用するような形式になっているところですね。詳しくはNode.js : exports と module.exports の違い(解説編)とかを読んでください。

実際のところいま必要かと言われれば僕は必要ないのですが、requireとか書いてあるJSライブラリも増えてきていますし、自分がやるかどうかはともかく、オープンソースの資源を使うときに必要だろうなと思って採用した次第です。

Gulpでこれまでやっていた方法

さて、Gulpを使い始めたのはつい最近なのですが、こんな方法を取っていました。

// Load libraries
var gulp = require('gulp'),
    $ = require('gulp-load-plugins')();
// JSHint and minify
gulp.task('js', function() {
     return gulp.src(['js/src/**/*.js', '!js/src/**/*.min.js'])
          .pipe($.jshint())
          .pipe($.jshint.reporter('jshint-stylish'))
          .pipe($.uglify())
          .pipe($.sourcemaps.init())
          .pipe($.concat('app.min.js'))
          .pipe($.sourcemaps.write())
          .pipe(gulp.dest('js'));
});

JSHintをかましてから圧縮してソースマップののち連結ですね。Uglifyは後の方がいいのかもしれませんが、まあこれでとりあえずオッケーだったわけです。

この方法は最終的にapp.min.jsさえあればよいという考え方です。

Browserifyで実現したかった方法

今回Browserifyを採用した趣味プロジェクトが「子供のためにブラウザゲームを作る」というものだったので、こんな感じの構成を目指しました。

js
├ src (元のソースを入れる)
│
├ lib (自作ライブラリを入れる)
│
├ dist (リリース用JSが入る)
│
└ vendor(外部ライブラリを入れる)

外部ライブラリっていうのは、CreateJSとかBox2DWebのことですね。自作ライブラリは作るかどうかわかりませんが、なんらかの処理をまとめたもので、src/*.jsからrequireされることを想定します。

たとえば、src/app.jsというファイルを作成したら、それにBrowserifyかまして圧縮&JSHintをかけて、dist/app.jsを生成するという次第です。もしパックマンを作りたくなったらsrc/packman.jsを作成して、それがdist/packman.jsとなります。上で紹介した例では、最終的にapp.min.js一つにしかなりませんでしたが、幾つ追加しても大丈夫というパターンです。

はまりポイント1. gulp-browserifyはNG

さて、上で紹介したコードと同じようにやるとすると、npm install gulp-browserify --save-dev とした上で$.browserify()で終わりかなーと思うのですが、なんとgulp-browserifyはブラックリスト入りしています。

理由はよく知りませんが、Gulpのプラグインであるgulp-browserifyは更新されないので、Browserifyはnodeのやつを使えということですね。

では、普通にBrowserifyを使うことにしましょう。

npm install browserify --save-dev

はまりポイント2. browserify().bundl()がなにか異なる

で、サンプルを見てみると……

gulp = require 'gulp'

browserify = require 'browserify'
source = require 'vinyl-source-stream'

gulp.task 'script', ->
     browserify
          entries: ['./js/src/main.coffee']
          extensions: ['.coffee'] # CoffeeScriptも使えるように
     .bundle()
     .pipe source 'main.js' # 出力ファイル名を指定
     .pipe gulp.dest "./js/" # 出力ディレクトリを指定

という感じになっています。coffeescriptですが、基本は同じです。が、どうもbundle()というメソッドが返す値はgulp.src()が返す値と異なるようで、そのまま.pipe(gulp.dest('js/dist'))とできないようです。

そこでこのサンプルではvinyl-source-streamというモジュールでgulpが扱える型(バイナルなんとか)に変換しているようなのですが、このときに名前を指定しています。

僕がやりたいことはgulp.src('js/src/**/*.js')とまとめて取得して、元の名前を保ったままjs/distフォルダに書き出したかったんですね。なので、このやり方はダメ。

はまりポイント3. transformしてbrowserifyに渡さないとダメ

いろいろググりたおした結果、次のようなことがわかりました。

  • 普通にgulp.src()gulp.dest()でパイプする
  • bowserifyの処理は専用の関数を作って、バイナルなんとか→文字列→browserify→バイナルなんとかに変換する処理を隠蔽する

なお、gulp + browserify, the gulp-y way というエントリーが特に参考になりました。

で、できたのがこんな感じ。

var gulp = require('gulp'),
    $ = require('gulp-load-plugins')(),
    browserSync = require('browser-sync'),
    browserify = require('browserify'),
    transform = require('vinyl-transform');

// Browserify
gulp.task('js', function(){
    // srcから受け取ったファイルをbrowserifyして
    // 返す関数を定義
    var browserified = transform(function(filename) {
        var b = browserify(filename);
        b.add(filename);
        return b.bundle();
    });

    return gulp.src('./js/src/*.js')
        .pipe(browserified) // ここで指定する
        .pipe($.uglify())
        .pipe($.sourcemaps.init({loadMaps: true}))
        .pipe($.sourcemaps.write('./map'))
        .pipe(gulp.dest('./js/dist/'));
});

sourcemapの位置がおかしいかもしれませんが、とりあえず目的は達成しました。

まとめ

こうした設定系のお仕事というのが日に日に複雑になっているように感じます。もう設定が仕事で、コード書くのはおまけなんじゃないかと思うこともよくありますね。

以前増田で見かけて感銘を受けた言葉に「はてぶ見てみろや。あいつら永遠にVimの設定やってるぞ」というものがありましたが、こうやって設定ばっかりしているうちに一行もコード書かずに死んでいくプログラマーもいるのかと思うと、自動化の闇は深いですな。終わり。

たった1日で即戦力になるExcelの教科書

たった1日で即戦力になるExcelの教科書 [書籍]

著者吉田 拳

出版社技術評論社

出版日2014 年 10 月 23 日

商品カテゴリー単行本(ソフトカバー)

ページ数328

ISBN4774168084

Excelでさえ1日で即戦力になれるというのに、Browserifyときたら……

Supported by amazon Product Advertising API

 

フォローしてください

ここで会ったのもなにかの縁。
高橋文樹.comの最新情報を見逃さないためにもフォローをお願いします。
めったに送らないメルマガもあります。

SPONSORED LINK

この記事について

この記事はが2015 年 4 月 6 日にプログラミングの記事として公開しました。

高橋先生の電子書籍

高橋先生の電子書籍

Amazonで電子書籍も買えます。

好きな言葉

どいつもこいつも不味いツラだ

— 尾崎紅葉

高橋先生の処女作

『途中下車』高橋文樹

2001年幻冬舎NET学生文学大賞受賞作です。

Web制作やります

Web制作やります

Web制作のご依頼は株式会社破滅派へ

不定期メルマガ

高橋文樹.comでは、不定期でニュースレターを配信しています。滅多に送らないので是非購読してください。

高橋文樹.comではプライバシーポリシーに準じて登録情報を取り扱います。