gruntで複数ディレクトリにあるSassファイルをコンパイルする

このエントリは「CSS Preprocessor Advent Calendar 2012」の18日目です。

さて、例えばサイト全体に適用したいSCSS(/_scss/foo.scss)と、あるカテゴリだけに適用したいSCSS(/category/_scss/bar.scss)があるような場合、コンパイルはどのようにしたらよいでしょうか。

解決する手段の一つとして、コマンドラインビルドツール「grunt」を利用する方法があります。今年初めに@Takazudoさんが「gruntでcompassをやや複雑にビルド」で紹介されているので二番煎じではありますが、2012年12月15日現在最新のgrunt v0.3.17と開発中のv0.4.0rc2で動作するコンパイルタスクを書いてみました。何かと便利で使っている方も多いと思われるcompassを利用したものです。

gruntでビルドしている様子

使い方

まだgruntを使っていない方にもチャレンジしていただけるよう、compassタスク等を含んだビルド環境のサンプルをダウンロードできるようにしました(compassタスクをまだgruntplugin化していない状態の時の環境ですが、動作結果は同じです)。node.js・Sass・Compassはインストールされているものとします。なお、Windowsでは開発中のgrunt v0.4.0a以降で正常に動作しました(gruntjs/grunt Issue #155)。

  1. gruntをインストールします。
    grunt v0.3.x
    npm install -g grunt
    • grunt v0.4.xが正式版になった際は、npm install -g grunt@0.3.17でインストール可能です。
    grunt v0.4.x
    npm install -g grunt-cli
    • コマンドラインインターフェースのみインストールします。gruntは手順3でプロジェクトディレクトリ内にインストールされます。
  2. githubのhideki-a / gruntTemplateをダウンロードして任意の場所に解凍します。
    • tasksディレクトリの内容はどちらも同一です。grunt.jsとGruntfile.jsの違いなどです。
    • 既にgruntをお使いの方は、npm install --save-dev git://github.com/hideki-a/grunt-compass-multidir.gitでプラグインのみインストールも可能です。
  3. ターミナル等で解凍してできたディレクトリ内に移動し、npm installを実行します。
  4. htdocs(名前は任意)を作成し、制作に必要なファイルを入れます。
  5. grunt.js / Gruntfile.jsの設定を行います。基本的に次のディレクトリ設定のみで良いと思います。必要に応じてconfig.rbを編集し、Sass(Compass)の設定を行って下さい。
     grunt.initConfig({
     compass: {
     dev: {
     reference: {
     // 'CSSを格納するディレクトリ': 'SCSSを格納するディレクトリ'
     'htdocs/common/css': 'htdocs/_scss',
     'htdocs/category/css': 'htdocs/category/_scss'
     },
  6. ターミナル等でgrunt developを実行し、ファイルの変更監視・コンパイルを開始します。

開発中は、FireSass for Firefox / Chromeでスタイルが記述してあるSCSSファイルの行番号が確認できるように、デバッグ情報を出力しています。制作完了時はgrunt compass:distでコンパイルすると、これらの情報を出力しないほか、compressed形式で出力するようになっています。

設定のヒント

add_import_pathについて

config.rb内に、コメントアウトしている設定項目「add_import_path」があると思います。これは、@importで読み込むSCSS(mixinを書いたSCSSファイルなど)が、@importを記述したSCSSと同階層になくても、add_import_pathで指定したパスにあればそこから読み込んでくれるようになる設定です。

これを利用すれば、カテゴリ別のSCSSを編集する際、メインのSCSSと共に格納しているmixinなどのSCSSファイルを利用することができます。自作フレームワークをプロジェクトディレクトリ外で管理し、add_import_pathを利用してフレームワークを読み込むような方法も考えられます。

forceの指定について

同一のconfig.rbを利用している場合、grunt compass:distを実行してもSCSSファイルが変更されていないと認識され、コンパイルが行われません。そこで、forceを指定して強制的に上書きするようにしています(Production Stylesheets | Compass Documentation)。

growl通知について

Macユーザーの多くが利用しているgrowlにコンパイルエラー通知を流すことができます。hideki-a / gruntTemplateのgrunt.js /Gruntfile.js内にあるgrowl設定をnotify: trueにしてお試し下さい。

Sassの変更監視・コンパイル以外のタスクについて

本題から少しそれますが、Sassを利用した制作の環境をより便利にしようという意味も兼ねて、上記compassタスク以外にもいくつかのタスクを利用できるようにしましたので紹介します。gruntを利用するきっかけになればと思います。

server(connect)タスク

まず、制作中のデータをブラウザで閲覧することができるスタティックWebサーバーが起動するserverタスク(grunt v0.4.x向けではconnectタスク)が入れてあります。閲覧先のURLをブラウザに入力するのも手間なので、openタスクで自動的に該当URLを開くようにもなっています。hostsを設定しなくても良いのが利点です。PHPを利用する際やSSIを利用する際は、serverタスクは利用せずApacheを利用します。

reload(reloadr)タスク

reloadタスク(grunt v0.4.x向けではreloadrタスク)は、Sassのコンパイル完了時やHTMLファイルの変更内容保存時などにブラウザの自動リロードを行います(LiveReloadエクステンションをブラウザにインストールして下さい)。エディタを問わず利用できますし、F5キーなどを押す必要がなくなるので、非常に作業効率が良くなります。

  • grunt v0.3.xではwatchタスクでファイルの変更を監視し、変更が発生した際にreloadタスクを実行する設定だったのですが、grunt v0.4.xでは上手く動作しないようです(webxl / grunt-reload Issue #13)。そのため、grunt-reloadrを使っているのですが、watchタスクと別にファイルの変更監視を行っているようで、ファイルの変更からブラウザの自動リロードまでに若干タイムラグが発生しました。grunt-contrib-livereloadが開発中のようなので、そちらに期待しようかと思います。

imgタスク

grunt v0.3.x向けにはimgタスクも入れてあります。imgタスクは、PNG・JPEG画像の最適化が行えます。compassで作成したCSSスプライト画像の最適化に使うのも良いかもしれません。

  • grunt v0.4.0向けの画像最適化プラグイン「grunt-contrib-imagemin」もありますが、まだ発展途上のような印象を受けました。

コンパイルの仕組み

参考までに...、task/compass.js内のregisterMultiTaskでcompassタスクの登録や設定情報の取得を行っています。コンパイルのコマンドはtask/lib/compass.jsに下記のようなコードが書かれており、registerMultiTaskのコード内で呼び出されて実行されます。

 compass = grunt.util.spawn({
 // 以下の指定が、compass compile --sass-dir htdocs/_scss --css-dir htdocs/common/css --config config.rb --environment developmentのようになる
 cmd: 'compass',
 args: ['compile'].concat(dirOption).concat(args)
 }, function (err, stdout, stderr) {
 if (stderr && grunt.config('growl').notify) {
 childProcess.exec('growlnotify -t "Grunt Compass Task" -m "Compile Error"');
 }
 });

なお、現在の課題は全ディレクトリをコンパイルしてしまうことです。開発途中のv0.4.0ではgrunt.file.watchFilesで変更されたファイル名が取得できていましたが、最新の開発版では取得できなくなりました(gruntjs/grunt-contrib-watch Issue #14)。変更されたファイル名の取得ができれば、変更ファイルのみのコンパイルが可能となり、パフォーマンス改善が期待できますので、こちらも今後に期待したいと思います。

まとめ

gruntを利用することで、複数ディレクトリのSassファイルも簡単にコンパイルしながら制作を進めることが分かりました。またコンパイルの設定も、grunt.js / Gruntfile.js / config.rbで、制約無く柔軟に行うことができます。さらに、reloadタスクなどを利用することで、制作作業を効率化することも可能です。

GUIでないので敷居が高いと感じられる方もいらっしゃるかもしれませんが、慣れてしまえば大変便利なので、一度チャレンジされてみてはいかがでしょうか。

参考

この記事のタグ