拡張子が.cssなファイルでもgulpを使ってSprocketsに無理やりasset pathを解決させる

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

背景

gulpでフロントエンドのビルドプロセスを組んでいるならSprocketsを通さなければ良い。
と言いたくても、なかなかそうすぐには完全移行はできず、ビルドしたものはapp/assets/配下に出力して最終的にはSprocketsさんにどうにかしてもらっている日々を過ごしています。

そんな中でscssのビルドをgulpに移行したのですが、Sprocketsでは.cssファイルではimage-urlasset-urlなどのhelperメソッドが使えず、imageのasset_pathが解決できません。

とはいえ、せっかくフロント側でlibsass使ってビルドしたものを.scss拡張子に戻して、再びSprocketsのScss Processorにかけるなんてリソースの無駄すぎて嫌だ。(libsassに比べると、ruby-sass遅過ぎる。)

じゃあ無理やり.css.erbに変換するか。erbなら余計な処理もなくて軽いでしょ、というのがこの記事でやることです。

参考

Rails4のpath解決については以下の記事を見ていただけると分かると思います。

http://qiita.com/wadako111/items/03bc00d914e62243a511

この記事で紹介されてる解決法1を実施するために、scssではなくerbに無理やりgulpで変換します。

コード

gulpfile.coffee
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

front/stylesheets/test.scss
.test-image-url {
  background-image: image-url('image.png');
}


.test-asset-url {
  background-image: asset-url('asset.png');
}

after

app/assets/stylesheets/test.css.erb
.test-image-url {
  background-image: url(<%= asset_path 'image.png' %>); }

.test-asset-url {
  background-image: url(<%= asset_path 'asset.png' %>); }

実際早いの

.erbに一度するのは確かに無駄ですが、ある程度大きいコードベースならば、それを余裕でペイするぐらいにはlibsassは爆速です。(詳細なデータは取ってません、すみません。)
Sprocketsからの脱却を目指している身としては、また目標に一歩近づいて精神衛生的にも良いです。