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