SinatraアプリでもAsset Pipelineを使う
Rails 3.1で追加されたAsset Pipelineという超便利な機能をSinatraでも使ってみます。
# Railsを使ったことはないですが。
Asset Pipelineとは
Asset Pipelineとは何か、ざっくり言うとJavaScript/CSSの依存関係を解決したり、複数ファイルを1つにまとめてリクエストを減らしたり、ついでに圧縮したりできる機能です。詳しくは以下のページが参考になると思います。
Asset Pipelineはsprocketsというgemを使って実現されており、Rails以外のRackアプリでも利用することができます。この記事では、Sinatraアプリでsprocketsを使ってみた例を紹介します。
利用方法
Sinatraからsprocketsを利用したサンプルを用意しました。
bundle installしてrackupすれば動作すると思います。が、私はpowでしか試していません。
git clone https://github.com/mono0x/sinatra-easy-template.gitcd sinatra-easy-templatebundle installrackup
Gemfile
必要なのはsprocketsだけですが、sprockets-helpersも入れておくと便利です。yui-compressorはコードを圧縮する場合に必要です。
gem 'sprockets'gem 'sprockets-helpers'gem 'yui-compressor', require: 'yui/compressor'
Sass(とCompass)を利用する場合は以下のgemを追加します。
gem 'sass'gem 'compass'gem 'sprockets-sass'
CoffeeScriptを利用する場合は以下のgemを追加します。
gem 'coffee-script'
application.rb
sprocketsに関する設定を行います。
set :sprockets, Sprockets::Environment.newconfigure do Sprockets::Helpers.configure do |config| config.environment = sprockets config.prefix = '/assets'
digestをtrueにすると、生成されるファイル名にファイルのハッシュ値が含まれるようになります。ファイルの中身が変わるたびにファイル名が変わるようになるので、ブラウザのキャッシュが読み込まれてしまってうまく表示できないトラブルを避けることができます。
config.digest = true end
ファイルを置く場所のパスを指定します。
sprockets.append_path 'assets/javascripts' sprockets.append_path 'assets/stylesheets'
js_compressorとcss_compressorにコードの圧縮を行うオブジェクトを指定できます。ここでは、production環境でのみYUI Compressorを利用するよう指定しています。
if production? sprockets.js_compressor = YUI::JavaScriptCompressor.new(munge: true, optimize: true) sprockets.css_compressor = YUI::CssCompressor.new endend
sprockets-helpersのメソッドを利用できるようにしておきます。
helpers Sprockets::Helpers
config.ru
/(root)はApplicationで、/assets以下はsprocketsで処理するようにします。
map '/assets' do run Application.sprocketsendmap '/' do run Applicationend
assets/stylesheets/application.css.scss
application.rbで指定したassets/stylesheetsディレクトリにCSSを配置します。.css.scssのように.cssの後ろにscss/sass/lessなどをつけておくと、それぞれの言語で記述したものとして認識されます。
sprocketsでは、ファイルの先頭に特別なディレクティブを記述すると、それを認識して動作します。以下の例では、requireディレクティブでlayout.css(.scss)を結合したあと、require_treeディレクティブでassets/stylesheets以下のすべてのスタイルシートを結合して1つのファイルにまとめています。requireディレクティブは結合する順序が重要な場合にのみ利用するもので、基本的にはrequire_treeディレクティブでごっそり結合しておけばよいと思います。なお、結合は一度のみしか行われないため、最後のrequire_treeディレクティブでは先にrequireしたlayoutは結合されません。
//= require layout//= require_tree .
views/layout.haml
stylesheet_pathメソッドにcssの名前を渡すことでパスを取得できます。cssがどんな形式で書かれているかを気にする必要はなく、名前のみを指定すればOKです。
%link{rel: 'stylesheet', type: 'text/css', href: stylesheet_path('application')}
実行結果
/index.html
ハッシュ値を含んだファイル名が生成されていることがわかります。
<link href="/assets/application-92ad097f0f535b5601a1b8a69fe89ffc.css" rel="stylesheet" type="text/css">ylesheet" type="text/css">
/assets/application-92ad097f0f535b5601a1b8a69fe89ffc.css
YUI Compressorで圧縮されたCSSが生成されています。
section,article,aside,header,footer,nav{display:block}#container{min-width:950px;width:80%;margin:0 auto;overflow:hidden;*zoom:1}#container>header{display:inline;float:left;overflow:hidden;width:99.974%;margin-right:1.042%}#container>section{display:inline;float:left;overflow:hidden;width:66.302%;margin-right:1.042%}#container>aside{display:inline;float:left;overflow:hidden;width:32.63%;margin-right:0}
さらに、以下のようなHTTPヘッダが付加されてキャッシュされるようになりました。
Cache-Control:public, max-age=3153600
つかってみた感想など
デフォルトでAsset Pipelineが使えるRailsと比べると準備が若干面倒ですが、設定さえしてしまえば便利だと感じました。
# ただ、Sinatraにいろいろ自分で足して使っていると、いい加減Railsを使った方がいいんじゃないかという気がしないでもないです。Padrinoなんてのもあるみたいですけど、それならメジャーなRailsにしたほうが無難かなと思いますし……。