gulpを使ってsassの@importを解決しつつ差分ビルドをする

  • 85
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

小さいアプリケーションなら、styleは変更がある度に毎回フルビルドしてしまっても1sもかからないかもしれない。
しかし大きくなって、5s以上かかると非常に苦痛だ。

というわけで差分ビルドしたい。

Sassの差分ビルドで問題になること

差分ビルド自体は簡単で、gulp-cachedとかを使えば、前回と差分があるものだけをビルドできる。

なんだけど、その場合に問題になるのがsassの依存関係(@import)の解決だ。

単純に差分のあったファイルをビルドするだけだと、@import元を辿れない。
そうすると@import元のファイルが変更についてこない。

いや、でもnode-sassのwatchオプションって@import元辿ってるよな、あれってどうなってるんだ??
と思って実装を見てみたら、sass-graphというnpmを使って辿っていた。

お、これ使えば差分ビルド時に依存関係の解決もできるんじゃね??

ということでgulp taskに組み込んでみた。

gulpfile.coffee

gulp        = require 'gulp'
forEach     = require 'gulp-foreach'
sass        = require 'gulp-sass'
cache       = require 'gulp-cached'
grapher     = require 'sass-graph'
gulpIf      = require 'gulp-if'

gulp.watching = false

gulp.task 'build:sass', ->
  baseDir = "front/stylesheets/"
  graph = grapher.parseDir(baseDir)
  gulp.src "#{baseDir}/**/*.scss"
    .pipe cache('sass')
    .pipe gulpIf(@watching, forEach (currentStream, file) ->
      files = [file.path]
      addParent = (childPath)->
        # ここで@import元をたどる
        graph.visitAncestors childPath, (parent) ->
          files.push(parent) unless _.includes(files, parent)
          addParent(parent)
      addParent(file.path)
      gulp.src files, {base: baseDir}
    )
    .pipe sass().on('error', sass.logError)
    .pipe gulp.dest("public/stylesheets")


gulp.task 'watch', ->
  @watching = true
  gulp.watch "front/stylesheets/**/*.scss", ['build:sass']

これのおかげで、10sかかかるビルドが0.1sで済むようになった。嬉しいね。