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

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

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

ディレクトリ構成

  • code
  • source
  1. Project
  2. ├─node_module
  3. │ Gruntfile.coffee
  4. │ package.json
  5. └─htdocs
  6. │ index.html
  7. ├─css
  8. │ style.min.css
  9. ├─img
  10. │ sprite-xxxx.png
  11. │ img-photo01.jpg
  12. ├─js
  13. │ project-name.js
  14. └─src
  15. ├─sass
  16. │ style.scss
  17. ├─css
  18. │ style.css
  19. ├─img
  20. │ │ sprite-xxxx.png
  21. │ │ img-photo01.jpg
  22. │ │
  23. │ └─src
  24. │ icon-aaa.png
  25. │ icon-bbb.png
  26. └─js
  27. aaa.js
  28. bbb.js
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で書いています)。

  • code
  • source
  1. module.exports = (grunt) ->
  2. grunt.loadNpmTasks 'grunt-contrib-watch'
  3. grunt.loadNpmTasks 'grunt-contrib-compass'
  4. grunt.loadNpmTasks 'grunt-contrib-uglify'
  5. grunt.loadNpmTasks 'grunt-contrib-concat'
  6. grunt.loadNpmTasks 'grunt-contrib-cssmin'
  7. grunt.loadNpmTasks 'grunt-contrib-imagemin'
  8. grunt.loadNpmTasks 'grunt-pngmin'
  9. grunt.loadNpmTasks 'grunt-styleguide'
  10. grunt.initConfig
  11. pkg: grunt.file.readJSON 'package.json'
  12. paths:
  13. srcDir: 'htdocs/src/'
  14. distDir: 'htdocs/'
  15. # Sassをコンパイル
  16. compass:
  17. dev:
  18. options:
  19. httpPath: '/'
  20. basePath: '<%= paths.srcDir %>'
  21. cssDir: 'css/'
  22. sassDir: 'sass/'
  23. imagesDir: 'img/'
  24. javascriptDir: 'js/'
  25. environment: 'development'
  26. # CSSを圧縮
  27. cssmin:
  28. minify:
  29. expand: true
  30. cwd: '<%= paths.srcDir %>css/'
  31. src: '**/*.css'
  32. dest: '<%= paths.distDir %>css/'
  33. # JPEG, GIF画像を圧縮
  34. imagemin:
  35. dynamic:
  36. options:
  37. optimizationLevel: 3
  38. files: [
  39. expand: true
  40. cwd: '<%= paths.srcDir %>img/'
  41. src: '**/*.{jpg, gif}'
  42. dest: '<%= paths.distDir %>img/'
  43. ]
  44. # PNG画像を圧縮
  45. pngmin:
  46. compile:
  47. options:
  48. ext: '.png'
  49. files: [
  50. expand: true
  51. cwd: '<%= paths.srcDir %>img/'
  52. src: '**/*.png'
  53. dest: '<%= paths.distDir %>img/'
  54. ]
  55. # JSファイルを結合
  56. concat:
  57. files:
  58. src: ['<%= paths.srcDir %>js/*.js']
  59. dest: '<%= paths.distDir %>js/<%= pkg.name %>.js'
  60. # JSファイルを圧縮
  61. uglify:
  62. options:
  63. banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
  64. compose:
  65. src: '<%= paths.distDir %>js/<%= pkg.name %>.js'
  66. dest: '<%= paths.distDir %>js/<%= pkg.name %>.min.js'
  67. # タスクをWatch
  68. watch:
  69. css:
  70. files: ['<%= paths.srcDir %>sass/*.scss', '<%= paths.srcDir %>css/*.css']
  71. tasks: ['compass:dev', 'cssmin']
  72. image:
  73. files: ['<%= paths.srcDir %>img/**/*.{png,jpg,gif}']
  74. tasks: ['imagemin:dynamic', 'pngmin']
  75. js:
  76. files: ['<%= paths.srcDir %>js/*.js', '<%= paths.distDir %>js/<%= pkg.name %>.js']
  77. tasks: ['concat', 'uglify:compose']
  78. grunt.registerTask 'default', ['watch']
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になるんですね。

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