config.rbを使わずにGruntfile側でcompassのコンパイルを制御する

config.rbを使わずにGruntfile側でcompassのコンパイルを制御する

CompassのコンパイルにGrunt.jsでWatchするケースは多々あると思います。その際にconfig.rbとGruntfile.coffeeに分けていたのですが、どうせなら設定ファイルは少ないほうが良いと思い、Gruntfile.coffeeに一本化しました。

ディレクトリ構成

Project
│  
├─node_module
│
│ Gruntfile.coffee
│ package.json
│   
└─htdocs
   │ 
   │ index.html
   │      
   ├─css
   │   style.min.css
   │      
   ├─img
   │   sprite-xxxx.png
   │   img-photo01.jpg
   │      
   ├─js
   │   project-name.js
   │          
   └─src
      ├─sass
      │   style.scss
      │     
      ├─css
      │   style.css
      │      
      ├─img
      │   │ sprite-xxxx.png  
      │   │ img-photo01.jpg
      │   │   
      │   └─src
      │      icon-aaa.png
      │      icon-bbb.png  
      │      
      └─js
          aaa.js
          bbb.js

srcフォルダが作業フォルダになります(srcフォルダは公開しない前提)。Gruntで自動化する流れと使用するモジュールは以下のようになります。

  1. grunt-contrib-compass src/sass内の.scssファイルをsrc/css内にコンパイルします。
  2. grunt-contrib-cssmin src/css内の.cssファイルををminifyし、css内に書き出します。
  3. grunt-pngmin compassで書きだされたスプライト画像はsrc/img内に書きだされます。最適化してimg内に書き出します。同様に単発の.pngファイルも最適化してimg内に書き出します。
  4. grunt-contrib-imagemin src/img内のJpeg画像やGif画像を最適化してimg内に書き出します。
  5. grunt-contrib-concat src/js内の.jsファイルを1ファイルに結合してjs内に書き出します。
  6. grunt-contrib-uglify js内に書きだされた.jsファイルを圧縮して.min.jsとリネームします。

Grantfile.coffeeは以下のようになります(.jsより.coffeeの方が見やすいのでCoffeeScriptで書いています)。

module.exports = (grunt) ->
    grunt.loadNpmTasks 'grunt-contrib-watch'
    grunt.loadNpmTasks 'grunt-contrib-compass'
    grunt.loadNpmTasks 'grunt-contrib-uglify'
    grunt.loadNpmTasks 'grunt-contrib-concat'
    grunt.loadNpmTasks 'grunt-contrib-cssmin'
    grunt.loadNpmTasks 'grunt-contrib-imagemin'
    grunt.loadNpmTasks 'grunt-pngmin'
    grunt.loadNpmTasks 'grunt-styleguide'
    grunt.initConfig
        pkg: grunt.file.readJSON 'package.json'
        paths:
            srcDir: 'htdocs/src/'
            distDir: 'htdocs/'
        # Sassをコンパイル
        compass:
            dev:
                options:
                    httpPath: '/'
                    basePath: '<%= paths.srcDir %>'
                    cssDir: 'css/'
                    sassDir: 'sass/'
                    imagesDir: 'img/'
                    javascriptDir: 'js/'
                    environment: 'development'
        # CSSを圧縮
        cssmin:
            minify:
                expand: true
                cwd: '<%= paths.srcDir %>css/'
                src: '**/*.css'
                dest: '<%= paths.distDir %>css/'
        # JPEG, GIF画像を圧縮
        imagemin:
            dynamic:
                options:
                    optimizationLevel: 3
                files: [
                    expand: true
                    cwd: '<%= paths.srcDir %>img/'
                    src: '**/*.{jpg, gif}'
                    dest: '<%= paths.distDir %>img/'
                ]
        # PNG画像を圧縮
        pngmin:
            compile:
                options:
                    ext: '.png'
                files: [
                    expand: true
                    cwd: '<%= paths.srcDir %>img/'
                    src: '**/*.png'
                    dest: '<%= paths.distDir %>img/'
                ]
        # JSファイルを結合
        concat:
            files:
                src: ['<%= paths.srcDir %>js/*.js']
                dest: '<%= paths.distDir %>js/<%= pkg.name %>.js'
        # JSファイルを圧縮
        uglify:
            options:
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
            compose:
                src: '<%= paths.distDir %>js/<%= pkg.name %>.js'
                dest: '<%= paths.distDir %>js/<%= pkg.name %>.min.js'
        # タスクをWatch
        watch:
            css:
                files: ['<%= paths.srcDir %>sass/*.scss', '<%= paths.srcDir %>css/*.css']
                tasks: ['compass:dev', 'cssmin']
            image:
                files: ['<%= paths.srcDir %>img/**/*.{png,jpg,gif}']
                tasks: ['imagemin:dynamic', 'pngmin']
            js:
                files: ['<%= paths.srcDir %>js/*.js', '<%= paths.distDir %>js/<%= pkg.name %>.js']
                tasks: ['concat', 'uglify:compose']
    grunt.registerTask 'default', ['watch']

パスは何らかで変更になった場合一括で変わってほしいので、変数に入れています。srcDirが作業フォルダへのパス、distDirが公開フォルダへのパスです。
config.rbに書いていた内容をgrunt-contrib-compassのoptionで設定していますが、config.rbと微妙に名前が違います(sassdirがsassDirなど)。ハマったのがprojectpathでgrunt側だとbasePathになるんですね。

いやぁ...やっぱり自動化って素敵!