gulpを導入した時に、Railsのasset pipelineを捨てた話。ハッシュ付きのファイル名が書いてあるmanifestファイルが何とかなればいい。それで大体何とかなった。今後もgulpを使い続けるか分からないし、もしかしたらnpm scriptsにまとめるかもしれないし、Railsからフロントエンド関連の作業を取り除いておきたかった。

移行した人の話

移行してみた

まずはasset pipelineをオフにする。それからgeneratorでアセットが生成されないようにする。

config/application.rb
config.assets.enabled = false
config.generators do |g|
g.assets false
end

それから、publicディレクトリの下にrev-manifest.jsonを出力する。gulp-rev-allでこのmanifestファイルを出力するので、npm installしておく。

"gulp-rev-all": "^0.9.7",

rev-manifest.jsonを出力するタスク。

rev.babel.js
import gulp from 'gulp';
import gulpLoadPlugins from 'gulp-load-plugins';
import rev from 'gulp-rev-all'
const $ = gulpLoadPlugins();
const dist = 'public/';
gulp.task('rev', ['styles:minify', 'scripts:minify'], () => {
return gulp.src([
dist + 'assets/styles/**/*.min.css',
dist + 'assets/scripts/**/*.min.js'
], {base: dist})
.pipe(rev.revision())
.pipe(gulp.dest(dist))
.pipe($.gzip())
.pipe(gulp.dest(dist))
.pipe(rev.manifestFile())
.pipe(gulp.dest(dist));
});

Railsからmanifestファイルを読み込むためのクラスを作る。参照サイトからパスを改変した。

config/initializers/asset_manifest.rb
require 'json'
class AssetManifest
def self.manifest
path = 'public/rev-manifest.json'
if File.exists?(path)
@manifest ||= fix_manifest(JSON.parse(File.read(path)))
end
end
def self.fix_manifest(manifest)
fixed = manifest.map{|orig_path, hashed_path|
orig_path = '/' + orig_path if orig_path != ?/
hashed_path = '/' + hashed_path if hashed_path != ?/
[orig_path, hashed_path]
}
Hash[fixed]
end
def self.stylesheet_path(url)
if AssetManifest.manifest
url += '.css' unless url.end_with?('.css')
AssetManifest.manifest[url] || url
else
url
end
end
def self.javascript_path(url)
if AssetManifest.manifest
url += '.js' unless url.end_with?('.js')
AssetManifest.manifest[url] || url
else
url
end
end
def self.asset_path(url)
if AssetManifest.manifest
AssetManifest.manifest[url] || url
else
url
end
end
end

ヘルパーの取得先もmanifestファイル経由に変更した。

app/helpers/application_helper.rb
module ApplicationHelper
def stylesheet_link_tag(url, options={})
url = AssetManifest.stylesheet_path(url)
super(url, options)
end
def crossorigin_javascript_include_tag(url, options={})
url = AssetManifest.javascript_path(url)
super(url, options)
end
def javascript_include_tag(url, options={})
url = AssetManifest.javascript_path(url)
super(url, options)
end
def image_tag(url, options={})
url = AssetManifest.asset_path(url)
super(url, options)
end
def image_path(url, options={})
url = AssetManifest.asset_path(url)
super(url, options)
end
def image_url(url, options={})
url = AssetManifest.asset_path(url)
super((ActionController::Base.asset_host || "") + url, options)
end
end

cssの読み込み方法はこんな感じになる。

<% if Rails.env.production? %>
<%= stylesheet_link_tag '/assets/styles/app.min.css', media: 'all' %>
<% else %>
<%= stylesheet_link_tag '/assets/styles/app.css', media: 'all' %>
<% end %>

ここまでの作業でRailsからフロントエンド関連の作業をgulpに移行できた。もちろんgulpじゃなくても、好きなツールで静的ファイルをビルドするといいと思う。