Gulpのインストールは1つでOK。複数のプロジェクトごとに設定ファイルを分割、さらに監視を行い、更新があったファイルのみタスクを実行させる方法

「1つの開発環境で複数のプロジェクトを管理」することって私はよくあります。

これまでは「プロジェクトが増えるたびにGulpをインストールする」運用をしていました。

ですが、この運用を続けていくと、プロジェクトが増えるごとにGulpのインストールが必要だし、npmパッケージやgulpプラグインも更新しないといけないし、タスクもプロジェクトごとに作る必要があるし、何よりディスク容量が増えてしまいますね。

図で表すと、以下のような状態です。

プロジェクトが増えるたびにGulpをインストールの図

これはあまり効率的とは言えない・・・

というわけで、この状態を解消するため「Gulpのインストールは1つにして、複数のプロジェクトを分割して管理する」方法を書きました。

プロジェクトごとに分割して管理する

Gulpをインストールしよう。複数のプロジェクトがあっても1つでOK

まず前提として、gulp-cliはグローバルにインストール済みとして進めます。インストールがまだの場合は、以下のページをご参考ください。

それではいきます~。

はじめに、開発用のフォルダ(今回は「dev」とします)を作って、コマンドプロンプト(またはターミナル)を起動して「dev」までcdコマンドで移動して、Gulpをインストールします。

Gulpをインストール

npm install gulp --save-dev

プロジェクトごとにファイルを作る

次に、Gulpをインストールしたフォルダ内に、プロジェクトファイルを格納する「projects」というフォルダを作成します。

「projects」フォルダ内には、プロジェクトごとに使いたいタスク、参照・監視するソース、出力先などを設定したファイルを作成します。

例えば、

  1. project1
  2. project2

という2つのプロジェクトがあるなら、以下のように「project1.js」「project2.js」ファイルを作成するイメージです。

project1.js

JavaScriptファイルを軽量化する「uglify」の参照ソースと出力先を指定しています。

module.exports = {
   uglify : {
      src: [ '../project1/*.js' ],
      dest: '../project1/out'
   }
}

project2.js

JavaScriptファイルを軽量化する「uglify」に加えて、CSSファイルを軽量化する「cssmin」の参照ソースと出力先を指定しています。

module.exports = {
   uglify : {
      src: [ '../project2/*.js' ],
      dest: '../project2/out'
   },
   cssmin : {
      src: [ '../project2/*.css' ],
      dest: '../project2/out'
   }
}

プロジェクトごとに「使いたいタスクも参照ソースも出力先もバラバラ」ってのがポイントです。

npmパッケージとgulpプラグインをインストールする

次に、コマンドプロンプト(またはターミナル)を起動して、Gulpをインストールしたフォルダ内で以下のコマンドを実行して、npmパッケージとgulpプラグインをインストールします。

run-sequence

タスクを直列、または並列に処理するために必要です。

npm install run-sequence --save-dev

merge-stream

ストリームをマージするために必要です。

npm install merge-stream --save-dev

gulp-changed

ファイルの変更があった場合にタスクを実行させるために必要です。

npm install gulp-changed --save-dev

gulp-uglify

JavaScriptファイルを軽量化するために必要です。インストールは以下の方法をご参考ください。

gulp-cssmin

CSSファイルを軽量化するために必要です。インストールは以下の方法をご参考ください。

インストールしたnpmパッケージとgulpプラグインの意味については、この時点でわからなくてもOKです。インストールして次に進みます。

npmパッケージとgulpプラグインを読み込む

次に、Gulpをインストールしたフォルダ内に「gulpfile.js」ファイルを作成して、インストールしたnpmパッケージとgulpプラグインを読み込みます。

var gulp = require('gulp'),
    glob = require('glob'),
    merge = require('merge-stream'),
    changed = require('gulp-changed'),
    runSequence = require('run-sequence'),
    uglify = require('gulp-uglify'),
    cssmin = require('gulp-cssmin');

このとき、gulpとglobもあわせて読み込みます。

プロジェクトファイルを読み込んで配列に格納

続いて、「projects」フォルダ内に作成したプロジェクトファイルをすべて読み込んで配列に格納します。「gulpfile.js」ファイルに追記します。

const CONFIGS = [];
glob.sync('./projects/*').forEach( function( filePath ) {
   CONFIGS.push( require( filePath ) );
});

タスクを作ってマージする

続いて、JavaScript,CSSそれぞれを軽量化するタスクを書きます。「gulpfile.js」ファイルに追記します。

//JavaScriptファイルを軽量化
gulp.task('jsmin', function () {
   var tasks = CONFIGS.map( config => {
      if( config.uglify ) {
         return gulp.src( config.uglify.src )
         .pipe( changed( config.uglify.dest ) )
         .pipe( uglify() )
         .pipe( gulp.dest( config.uglify.dest ) );
      } else {
         return gulp.src( './' );
      }
   });

   return merge(tasks);
});

//CSSファイルを軽量化
gulp.task( 'cssmin', function () {
   var tasks = CONFIGS.map( config => {
      if( config.cssmin ){
         return gulp.src( config.cssmin.src )
         .pipe( changed( config.cssmin.dest ) )
         .pipe( cssmin() )
         .pipe( gulp.dest( config.cssmin.dest ) );
      } else {
         return gulp.src( './' );
      }
   });

   return merge(tasks);
});

プロジェクトファイルに設定が見つからない場合はエラーになってしまうので、条件分岐をして「gulp.src( ‘./’ )」を返して、何も処理をさせていません。

この処理を加えることで、プロジェクトごとにファイルの内容が変わっていても柔軟に対応できるかな、とは思っています。

ファイルを監視する

最後に、監視したいファイルをそれぞれタスク別に配列に格納して、ファイルが変更されたらタスクが実行されるようにします。「gulpfile.js」ファイルに追記します。

gulp.task('watch', () => {
   var jsminSrc = [];
   var cssminSrc = [];

   CONFIGS.forEach(config => {
      if( config.uglify ){
         jsminSrc.push( config.uglify.src );
      }
      if( config.cssmin ) {
         cssminSrc.push( config.cssmin.src );
      }
   });
   gulp.watch( jsminSrc, () => runSequence('jsmin') );
   gulp.watch( cssminSrc, () => runSequence('cssmin') );

});

以上でgulpfile.jsの追記は終わりです。ここまでできたら、実際にファイルを監視してみます。

Gulpをインストールしたフォルダ内で、以下のコマンドを実行します。

gulp watch

以下のファイルが監視対象となります。

監視対象となるファイル

  • project1/*.js (project1フォルダ直下のjsファイルすべて)
  • project2/*.js (project2フォルダ直下のjsファイルすべて)
  • project2/*.css (project2フォルダ直下のcssファイルすべて)

上記の監視対象となるファイルが変更されたら、該当するタスクが実行されて、プロジェクトファイルごとに指定した出力先にファイルが作成されます。

まとめ

この方法を使えば、Gulpのインストールはプロジェクトごとに作る必要はなくなります。1つでOK。

npmパッケージやgulpプラグインのアップデートなどの維持の手間も少なくなりますね。

また、プロジェクトが増えれば「projects」フォルダにプロジェクトファイルを作って、使いたいタスクと参照ソース、出力先などを書けばいいだけです。

新しくタスクを増やしたい場合はgulpfile.jsに同じ要領で書いていけばいいですね。

タスク分割の方法はよく見るけど、プロジェクト分割の方法はあまり見つけられなかった

ところで、Gulpは「タスクが増えるごとに肥大化するgulpfile.jsファイルをどうにかしたい」という目的で「タスクごとに分割して管理する」方法をよく見かけますね。

プロジェクトを分割できたので、タスクも分割すると、もっとすっきりとしたファイルや構成になるかもですね。この辺は、合間を見ながら徐々に改良していこうと思います。

逆に、今回ご紹介したプロジェクトを分割する方法については、ほとんど情報を見つけることができなくて、自分なりに効率の良い方法を探しながらやっています。

情報が少ない中で、こちらのページ「Multiple Sources in GulpJS」は大変参考になりました。ありがとうございます。

「他にももっといい方法があるよ!」という場合は、是非ともご教示いただけますと幸いです。

著者:bouya Imamura