背景
gulpでフロントエンドのビルドプロセスを組んでいるならSprocketsを通さなければ良い。
と言いたくても、なかなかそうすぐには完全移行はできず、ビルドしたものはapp/assets/
配下に出力して最終的にはSprocketsさんにどうにかしてもらっている日々を過ごしています。
そんな中でscssのビルドをgulpに移行したのですが、Sprocketsでは.cssファイルではimage-url
やasset-url
などのhelperメソッドが使えず、imageのasset_pathが解決できません。
とはいえ、せっかくフロント側でlibsass使ってビルドしたものを.scss
拡張子に戻して、再びSprocketsのScss Processorにかけるなんてリソースの無駄すぎて嫌だ。(libsassに比べると、ruby-sass遅過ぎる。)
じゃあ無理やり.css.erb
に変換するか。erbなら余計な処理もなくて軽いでしょ、というのがこの記事でやることです。
参考
Rails4のpath解決については以下の記事を見ていただけると分かると思います。
この記事で紹介されてる解決法1を実施するために、scssではなくerbに無理やりgulpで変換します。
コード
gulp = require 'gulp'
sass = require 'gulp-sass'
replace = require 'gulp-replace'
rename = require 'gulp-rename'
gulp.path =
app: 'front'
dist: 'app/assets'
gulp.task 'build:sass', ->
styleAssetPattern = /(?:image-url|asset-url)\(['"](.+)['"]\)/g
replaceStyleAssetPath = (_full, key) -> "url(<%= asset_path '#{key}' %>)"
gulp.src "#{@path.app}/stylesheets/**/*.scss"
.pipe sass({includePaths: [ '.tmp/stylesheets' ]})
.pipe replace(styleAssetPattern, replaceStyleAssetPath)
.pipe rename({ extname: '.css.erb' })
.pipe gulp.dest("#{@path.dist}/stylesheets")
解説
gulp-replaceで、正規表現を使って本来のscssファイルで使っていた(image-url|asset-url)
の引数を抜き出して、erbで使えるasset_path
に変換しています。
その上でgulp-renameで拡張子を.css.erb
に変換します。
結果
before
.test-image-url {
background-image: image-url('image.png');
}
.test-asset-url {
background-image: asset-url('asset.png');
}
after
.test-image-url {
background-image: url(<%= asset_path 'image.png' %>); }
.test-asset-url {
background-image: url(<%= asset_path 'asset.png' %>); }
実際早いの
.erbに一度するのは確かに無駄ですが、ある程度大きいコードベースならば、それを余裕でペイするぐらいにはlibsassは爆速です。(詳細なデータは取ってません、すみません。)
Sprocketsからの脱却を目指している身としては、また目標に一歩近づいて精神衛生的にも良いです。