gulp + Browserify(+ debowerify)という構成でWebサイトを作っていると、SASSにもdebowerify相当のものが欲しくなってくる。

ちなみに、debowerify というのは、

var Velocity = require("velocity");

というJavaScriptを、

var Velocity = require("./../../bower_components/velocity/velocity.js");

という風に、bower_components内のパスに解決してくれるBrowserify transformだ。 欲しいのはこれのSASS版。

「あったらいいのにな〜」と思うようなライブラリはGithubで検索すれば必ず出てくる。はずだったが、無かった。

そこで decomposer というgulpプラグインを作った。

使い方

まずはnpm install --save-dev gulp gulp-sass decomposerで必要なものをインストールしておく。既存のプロジェクトに追加するならdecomposerだけでいい。

gulpfile.js はこのように定義しておく。

var gulp = require('gulp');
var sass = require('gulp-sass');
var decomposer = require('decomposer');

gulp.task('styles', function() {
  gulp.src('src/styles/**/*.sass')
    .pipe(decomposer())
    .pipe(sass({indentedSyntax: true}))
    .pipe(gulp.dest('dist/css'));
});

ポイントはsass よりも前decomposerを挟むこと。なぜなら、外部から@importしたmix-insや変数はSASSコンパイル時に解決されるからだ。sassよりも後に置くと、SASSが@importを解決出来ずにエラーが発生する。

続けてSASSを書こう。

@import normalize.sass
@import styles/font

body
  font-family: $ff-gothic

$ff-gothicuetchy/stylesfont.sass で定義されているfont-familyだ。

最後にBowerを使って必要なアセットをインストールする。

bower i --save normalize.sass
bower i --save uetchy/styles

これで完成。後はgulp stylesを実行するだけだ。

ファイルパス解決時のポイント

decomposer はBowerモジュールに入っている任意のファイルを指定して@importすることが出来る。 記法はこのようになる。

@import [Bowerモジュール名]/[ファイル名]

例えば、よく使うスタイルをまとめた uetchy/styles の___font.sass__ を@importするなら、

@import styles/font

と書ける。 ここでもし@import stylesと、ファイル名を省略して書くとどうなるのだろうか? コンパイルに失敗する? そんなことはない。

モジュール名だけを書くと、decomposerは__bower.json__に書かれているmainファイルを見つけ出して、それを@importしてくれるのだ。

もしmainファイルが複数指定されていたら、index.sass[モジュール名].sass、または__mainっぽい名前__ を持つファイルを@importする。

つまり、

@import normalize.sass

と書けば、

@import ../bower_components/normalize.sass/normalize.sass

という風に解決される。

まとめ

これでスタイルの@importをすっきり書けるようになった。 とはいえ、component対応やPlain CSSのインライン展開や.less対応など、追加したい機能は色々ある。

もしContributionに興味があるなら、Githubリポジトリをフォークしてほしい。