config.rbを使わずにGruntfile側でcompassのコンパイルを制御する
CompassのコンパイルにGrunt.jsでWatchするケースは多々あると思います。その際にconfig.rbとGruntfile.coffeeに分けていたのですが、どうせなら設定ファイルは少ないほうが良いと思い、Gruntfile.coffeeに一本化しました。
ディレクトリ構成
- code
- source
- 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
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で自動化する流れと使用するモジュールは以下のようになります。
- grunt-contrib-compass src/sass内の.scssファイルをsrc/css内にコンパイルします。
- grunt-contrib-cssmin src/css内の.cssファイルををminifyし、css内に書き出します。
- grunt-pngmin compassで書きだされたスプライト画像はsrc/img内に書きだされます。最適化してimg内に書き出します。同様に単発の.pngファイルも最適化してimg内に書き出します。
- grunt-contrib-imagemin src/img内のJpeg画像やGif画像を最適化してimg内に書き出します。
- grunt-contrib-concat src/js内の.jsファイルを1ファイルに結合してjs内に書き出します。
- grunt-contrib-uglify js内に書きだされた.jsファイルを圧縮して.min.jsとリネームします。
Grantfile.coffeeは以下のようになります(.jsより.coffeeの方が見やすいのでCoffeeScriptで書いています)。
- code
- source
- 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']
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になるんですね。
いやぁ...やっぱり自動化って素敵!