Gruntで快適な環境を整備したい!【タスク記述編】



『Gruntで快適な環境を整備したい!【インストール編】』に引き続き、タスクの自動化ツールであるGruntを使ってみます。今回はタスク記述編ということで、様々なタスクを書いてみます。
 

今回したいこと

 
今回は以下のタスクを書いてみたいと思います。タスクはGruntfile.jsに書きます。ベースとなるコードは前回の記事『Gruntで快適な環境を整備したい!【インストール編】』の「Gruntfile.jsを作成する」をご覧ください。
 


タスクの中身は基本的に、処理対象となるファイルやフォルダのパスと処理後のパスで構成されています。ファイルパスの書き方には「コンパクト形式」「ファイルオブジェクト形式」「ファイル配列形式」があります。Gruntのドキュメントを日本語化してくださっているサイトがありますので、こちらを参考にしてください。プラグインによってはサポートしていない形式があるようですので、どのプラグインがどの形式をサポートしているかは各プラグインのドキュメントを参照してください。
 

 ■ファイル、フォルダの複製

 
ファイル、フォルダの複製にはgrunt-contrib-copyを使います。納品用に必要なファイルをすべてbuildフォルダ下にコピーしてみます。

  copy: {
    dist: {
      files: [{
         src: [‘assets/**’,’css/**’,’js/**’,’index.html’],
         dest: ‘build/’
      }]
    }
  },

 

 ■ファイルの連結

 
複数のファイルの連結にはgrunt-contrib-concatを使います。下記では、foo.js、bar.js、baz.jsを1ファイルに連結し、(package.jsonで設定した名前).jsにしています。package.jsonの値は、「<%= pkg.name %>」のような形で取得できます。たとえばpackage.jsonで「riaxdnp」というプロジェクト名をnameに設定している場合、riaxdnp.jsというJSがjsフォルダ下に新たに作成されます。

   concat: {
     options: {
       // 結合したファイルの頭にコメント入れたいとき
       banner: “/* test */\n”
     },
     dist: {
       // 出力元
       src: [
         ”build/js/foo.js”,
         ”build/js/bar.js”,
         ”build/js/baz.js”
       ],
       // 出力先( package.jsonのnameから値を取得している)
       dest: “build/js/<%= pkg.name %>.js”
     }
   },

 

 ■JSのminify

 
JavaScriptファイルの縮小化にはgrunt-contrib-uglifyを使います。ここでは、元となるファイルのsrcに「<%= concat.dist.dest %>」を指定し、上記のconcatで1ファイルにまとめたJSを元にminifyしてみます。このように、他のタスクの値を取得することも可能です。

   uglify: {
      main: {
         src: “<%= concat.dist.dest %>“,
         dest: “build/js/<%= pkg.name %>.min.js”
      }
   },

 

 ■CSSのminify

 
CSSファイルの縮小化にはgrunt-contrib-cssminを使います。下記では、foo.css、bar.css、baz.cssの3つのCSSをまとめて(package.jsonで設定した名前).min.cssという1つのファイルにしています。(事前にconcatしなくて良いので便利です。もちろんJSのminifyでも同じことができます。)

   cssmin: {
      main: {
         src : [‘build/css/foo.css’,’build/css/bar.css’,’build/css/baz.css’],
         dest : ‘build/css/<%= pkg.name %>.min.css’
      },
      // パスが違う場合はこのようにタスクを複数書くこともできます。
      // devという名前は任意で付けています
      dev: {
         src : [‘build/dev/css/*’],
         dest : ‘build/dev/css/<%= pkg.name %>.min.css’
      }
   },

 

 ■不要なファイルの削除

 
フォルダ、ファイルの削除にはgrunt-contrib-cleanを使います。CSSとJSを縮小化したので、ここでは元となったファイルを削除してみます。すべて他のタスクの設定値を利用していますが、パスを記述してももちろん問題ありません。

   clean: {
      // concatで設定したfoo.js bar.js baz.jsが削除されます。
      mainJS: [“<%= concat.dist.src %>“],
      // concatのタスクで生成されたname.jsが削除されます。
      concatJS: [“<%= replace.dist.dest %>“],
      // cssminで設定したfoo.css bar.css baz.cssと、dev/css下のすべてのファイルが削除されます
      css: [“<%= cssmin.main.src %>“,”build/dev/css/*”]
   },

 

 ■ファイルの更新監視

 
ファイルの更新を監視して、何かのタスクを都度実行したい際にはgrunt-contrib-watchを使います。以下では、jsフォルダ内のjsファイルの変更を監視し、ドキュメントの生成と構文チェックを行っています。

   watch: {
      doc: {
         // 変更を監視するファイルを指定
         files: [“js/”,”Gruntfile.js”],
         // 変更されたらどのタスクを実行するか
         tasks: [“jshint”,”yuidoc”]
      }
   },

 

 ■JSの構文チェック

 
JSの構文チェックにはgrunt-contrib-jshintを使います。optionsでjshintの設定ファイルであるjshintrcを指定しています。チェック対象にGruntfile.js自身も入れておくと便利です。

   jshint: {
      options: {
         jshintrc: “.jshintrc”
      },
      // 対象ファイルを指定
      all: [“js/”]
   },

 

 ■YUIDocによるドキュメント生成

 
ドキュメントの生成にはgrunt-contrib-yuidocを使います。pathsで元のJSのフォルダやファイルのパスを、outdirで生成済みのドキュメントを格納したいフォルダを指定します。

   yuidoc: {
      dist: {
         ’name’: ‘Test Web App’,
         ’description’: ”,
         ’version’: ‘0.1.0’,
         options: {
            paths: [‘js/’],
            outdir: ‘docs/’
         }
      }
   }

 

実行するためにタスクをまとめる

 
最後に、ここまでで書いてきたタスクをまとめてみます(使用したプラグインの読み込み部分の記述も忘れずに!)。grunt.registerTaskでタスクの設定を行います。defaultは「grunt」コマンドを入力した際のデフォルトタスクの設定で、buildは任意で付けたタスク名です。下記ではデフォルトでwatch(更新の監視)を行い、「grunt build」が入力された場合はcopy、concat、uglify、cssmin、cleanの順番でタスクが実行されます。

grunt.registerTask(‘default’, [‘watch’]);
grunt.registerTask(‘build’, [‘copy’,’concat’,’uglify’,’cssmin’,’clean’]);

 

まとめ

 
いかがだったでしょうか。基本的な構成はオブジェクトと配列の組み合わせで、パスを指定していく単純な仕組みだということがおわかりいただけると思います。環境の導入とタスクの記述には少し労力がかかりますが、一度作成すればその後はかなり楽です。また、リポジトリでpackage.jsonとGruntfile.jsを共有すれば、プロジェクト内で同じビルドタスクを使用することも可能です。簡単な1つのタスクからでもいいので、導入を検討してみてはいかがでしょうか。それでは~。