blog

これからはじめる Gulp シリーズこれからはじめるGulp(7):require-dirモジュールを使ったタスク単位のファイル分割

    • Ryuichi Nonaka
    この記事は書かれてから1年以上経過しており、内容が古い場合があります。

    はじめに

    この記事はGulp.js(全俺) Advent Calendar 2014です。

    前回のこれからはじめるGulp(6):gulp-plumberとgulp-notifyを使ったデスクトップ通知でgulp-plumberとgulp-notifyを使ったエラー等のデスクトップ通知を試しました。今回はタスクに含まれるパスを整理しつつrequire-dirモジュールを使ったタスク単位のファイル分割を試します。

    パスの整理

    まずはパスの指定を整理しておきます。必須ではありませんが、何かと便利なPathモジュールも読み込んでおきます。Pathモジュールはファイルパスを扱うユーティリティが用意されており、パスの正規化やパスの中からディレクトリ部分・ファイル名の部分だけ取得するといったメソッドが用意されている便利なモジュールです。

    Pathモジュールを読み込む

    Pathモジュールはnode.jsのCoreモジュールなのでインストール不要です。require()で読み込むだけですぐに利用できます。

    var gulp      = require('gulp');
    var path      = require('path'); //<-
    var sass      = require('gulp-sass');
    var connect   = require('gulp-connect');
    var plumber   = require('gulp-plumber');
    var notify    = require('gulp-notify');
    
    ...
    

    パスを変数から呼び出す

    gulpfile.jsで色々タスクで指定しているsrc, prodのディレクトリパスを管理するオブジェクトを作ります。

    //option
    var paths = {
      srcDir : 'src',
      dstDir : 'prod'
    }
    

    gulpfile.js1つで管理している場合は1カ所、後半のタスク毎にファイルを分割する場合はファイル毎に必要なパスをこれで管理します。

    タスクのglobをタスクのローカル変数で管理する

    glob(パスのパターン:scss/**/*.scss等)をローカル変数に定義して管理しやすくします。

    gulp.task('sass', function(){
      var srcGlob = paths.srcDir + 'scss/*.scss';
      var dstGlob = paths.dstDir + 'css';
      var errorMessage = "Error: <%= error.message %>";
    
      gulp.src( srcGlob )
        .pipe(plumber({
          errorHandler: notify.onError( errorMessage )
        }))
        .pipe(sass())
        .pipe(gulp.dest( dstGlob ))
        .pipe(connect.reload());
    });
    

    全体を整理すると最終的にこうなります。

    var gulp      = require('gulp');
    var path      = require('path');
    var sass      = require('gulp-sass');
    var connect   = require('gulp-connect');
    var plumber   = require('gulp-plumber');
    var notify    = require('gulp-notify');
    
    //option
    var paths = {
      srcDir : 'src',
      dstDir : 'prod'
    }
    
    //sass
    gulp.task('sass', function(){
      var srcGlob = path.join( paths.srcDir, 'scss', '*.scss' );
      var dstGlob = path.join( paths.dstDir, 'css' )
      var errorMessage = "Error: <%= error.message %>";
    
      gulp.src( srcGlob )
        .pipe(plumber({
          errorHandler: notify.onError( errorMessage )
        }))
        .pipe(sass())
        .pipe(gulp.dest( dstGlob ))
        .pipe(connect.reload());
    });
    
    
    //copy
    gulp.task('copy', function(){
      var srcGlob = paths.srcDir + '/*.html';
      var dstGlob = paths.dstDir;
    
      gulp.src( srcGlob )
        .pipe(gulp.dest( dstGlob ))
        .pipe(connect.reload());
    });
    
    
    //watch
    gulp.task('watch', ['sass', 'copy'], function(){
      var scssWatchGlob = paths.srcDir + 'scss/*.scss';
      var htmlWatchGlob = paths.srcDir + '/*.html';
    
      gulp.watch( scssWatchGlob, ['sass']);
      gulp.watch( htmlWatchGlob, ['copy']);
    });
    
    
    //server
    gulp.task('serve', function(){
      connect.server({
        root: paths.dstDir,
        livereload: true
      });
    });
    
    //default
    gulp.task('default', ['watch', 'serve']);
    

    タスク毎にファイルを分割する

    続いて本題のファイル分割です。タスク毎にファイルを分割するにはrequire-dirモジュールを使います。require-dirモジュールはディレクトリ内のjavascript, jsonファイルを自動で読み込んでくれます。オプションを有効にすると下層のディレクトリにあるファイルも再帰的に読み込めます。

    require-dirのインストール

    いつも通りrequire-dirを開発環境用にインストールします。

    $ sudo npm install require-dir --save-dev
    Password:
    require-dir@0.1.0 node_modules/require-dir
    

    require-dirの読み込み

    require-dirモジュールは下記のように読み込み、ディレクトリを指定します。

    var requireDir = require('require-dir');
    var dir        = requireDir('./tasks');
    

    また、下層ディレクトリにあるファイルも再帰的に呼び出したい場合はオプションのrecurse: trueを有効にします(デフォルトでは無効になっています)。

    var requireDir = require('require-dir');
    var dir        = requireDir('./tasks', {recurse: true});
    

    ファイルを分ける

    それではタスク毎にファイルを分けたいと思います。分ける際、タスクに使われているプラグインやモジュールの指定もそれぞれに指定しなければいけません。ここではsassタスクとcopyタスクを別ファイルにします gulpfile.jsにはdefaltタスクから直接呼び出すserveタスクとwatchタスクを残します。serveタスクを別ファイルにしてしまうとLiveReloadが効かなくなるので注意してください。

    gulpfile.js

    var gulp       = require('gulp');
    var requireDir = require('require-dir');
    var dir        = requireDir('./tasks');
    var path       = require('path');
    var connect    = require('gulp-connect');
    
    //option
    var paths = {
      srcDir : 'src',
      dstDir : 'prod'
    }
    
    //serve
    gulp.task('serve', function(){
      connect.server({
        root: paths.dstDir,
        livereload: true
      });
    });
    
    //watch
    gulp.task('watch', ['sass', 'copy'], function(){
      var scssWatchGlob = paths.srcDir + 'scss/*.scss';
      var htmlWatchGlob = paths.srcDir + '/*.html';
    
      gulp.watch( scssWatchGlob, ['sass']);
      gulp.watch( htmlWatchGlob, ['copy']);
    });
    
    
    //default task
    gulp.task('default', ['watch', 'serve']);
    

    sassタスクとcopyタスク

    以下のように別ファイル化するsassタスクとcopyタスクはtasksディレクトリに保存されます。

    $ tree tasks
    tasks
    ├── copy.js
    └── sass.js
    

    sass.js

    var gulp       = require('gulp');
    var path       = require('path');
    var sass       = require('gulp-sass');
    var plumber    = require('gulp-plumber');
    var notify     = require('gulp-notify');
    var connect    = require('gulp-connect');
    
    //option
    var paths = {
      srcDir : 'src',
      dstDir : 'prod'
    }
    
    //task
    gulp.task('sass', function(){
      var srcGlob = paths.srcDir + 'scss/*.scss';
      var dstGlob = paths.dstDir + '/css';
      var errorMessage = 'Error: <%= error.message %>';
    
      gulp.src( srcGlob )
        .pipe(plumber({
          errorHandler: notify.onError( errorMessage )
        }))
        .pipe(sass())
        .pipe(gulp.dest( dstGlob ))
        .pipe(connect.reload());
    });
    

    copy.js

    var gulp       = require('gulp');
    var connect    = require('gulp-connect');
    
    //option
    var paths = {
      srcDir : 'src',
      dstDir : 'prod'
    }
    
    //task
    gulp.task('copy', function(){
      var srcGlob = paths.srcDir + '/*.html';
      var dstGlob = paths.dstDir;
    
      gulp.src( srcGlob )
        .pipe(gulp.dest( dstGlob ))
        .pipe(connect.reload());
    });
    

    気になかった方も多いかもしれませんが、module.exports = function(gulp) {がありません。どんな風に処理されているのかまで把握できていませんがとりあえず$ gulpで動くことが確認できました。

    まとめ

    タスクもファイル毎に分けることができ、パスも整理できました。Grantに比べてパフォーマンスも良く書いていて楽しいですね。明日からより複雑な処理ができるようGulpの同期処理について勉強したいと思います。

    シリーズ

    1. これからはじめるGulp(0):アドベントカレンダースケジュール
    2. これからはじめるGulp(1):bundler, rbenv, nodebrewでGulp環境を作ってみる
    3. これからはじめるGulp(2):gulp-sassを使ってSCSSをコンパイルするタスクを作ってみる
    4. これからはじめるGulp(3):gulp.watchでファイルの変更を監視しタスクを実行する
    5. これからはじめるGulp(4):gulp-connectモジュールを使ったローカルサーバの起動
    6. これからはじめるGulp(5):gulp-connectモジュールを使ったLiveReload
    7. これからはじめるGulp(6):gulp-plumberとgulp-notifyを使ったデスクトップ通知
    8. これからはじめるGulp(7):require-dirモジュールを使ったタスク単位のファイル分割
    9. これからはじめるGulp(8):delモジュールとvinyl-pathsモジュールを使ったファイルの削除
    10. これからはじめるGulp(9):Ruby版Sassが使えるgulp-ruby-sassへの乗り換え
    11. これからはじめるGulp(10):deprecatedになっていたgulp-connectからgulp-webserverへ乗り換える
    12. これからはじめるGulp(11):ブラウザ間でスクロールやクリック操作を同期できるBrowserSync
    13. これからはじめるGulp(12):gulp-imageminプラグインを使ったJPEG,PNG,GIF,SVGの最適化
    14. これからはじめるGulp(13):gulp-changedプラグインで変更されたファイルだけを処理させる
    15. これからはじめるGulp(14):gulp-cachedプラグインで変更されたSCSSファイルだけを処理させる
    16. これからはじめるGulp(15):gulp-responsiveプラグインを使ったレスポンシブイメージ作成の自動化
    17. これからはじめるGulp(16):gulp-image-resizeプラグインを使ってサムネイルやレスポンシブイメージを作る
    18. これからはじめるGulp(17):SketchTool(Sketch 3 command line tool)を使ったアートボード・スライスの書き出しとgulp-execプラグインを使ったSketchtoolの呼び出し
    19. これからはじめるGulp(18):SketchToolで何ができるのかコマンドと主要なオプションを使ってみる
    20. これからはじめるGulp(19):gulp-sketchとgulp-execを使ったSketch 3デザインデータの画像書き出し
    21. これからはじめるGulp(20):Node.jsのChild Processモジュールを使ってgulpからjekyllのbuildコマンドを実行する
    22. これからはじめるGulp(21):gulp-awspublishプラグインを使ったAmazon S3への静的Webサイトパブリッシュ
    23. これからはじめるGulp(22):gulp-iconfontとgulp-sketchを使ったアイコンフォント作成の自動化
    24. これからはじめるGulp(23):gulp-consolidateでgulp-iconfontで作ったアイコンフォントのシンボル一覧HTMLを作る
    25. これからはじめるGulp(24):gulp.spritesmithプラグインでSpriteイメージを作る
    26. これからはじめるGulp(25):Hologramとgulp-hologramでスタイルガイドを作る
    27. これからはじめるGulp(26):Sketch3のサブディレクトリ書き出しに対応したgulp-sketchを試す

    コメント・フィードバック