Edited at

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

More than 3 years have passed since last update.

小さいアプリケーションなら、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で済むようになった。嬉しいね。