Time to Read
5分
アセットパイプラインなどで使えるとして話題の Sprockets gem 、自分向けまとめ。確認しないで書いているところもあります。
アセットパイプラインを支える技術 – sprockets
Web assets 、具体的には主に CSS と JavaScript の圧縮/依存性の解決/各種ソースからの変換をサポートするための Rubygem 。 asset とは資産、財産の意。
執筆時点現在のバージョンは 2.0.3 。なお、 rack-sprockets gem は、 sprockets(<~ 1.0) 、要するに1.x系に依存するので利用をお勧めしない。
具体的には、
1 2 3 4 5 6 7 8 9 10 11 | require 'sprockets' map '/assets' do environment = Sprockets::Environment.new environment.append_path 'app/assets/javascripts' environment.append_path 'app/assets/stylesheets' run environment end map '/' do run YourRackApp end |
こういうコードが出現する。
Sprockets::Environment のインスタンスを、たとえば /assets, /resources のようなディレクトリの下にマッピングして用いることが多い。 Sprockets::Environment のインスタンス自体は Rack Middleware ではない 。 Rack アプリケーションそのもの 。
上記コードのように、 /assets 以下に配備し、ロードパス 'app/assets/javascripts','app/assets/stylesheets'を append_path メソッドにより追加すると、実際にクライアントからアクセスする PATH_INFO と実ファイルの対応付けはたとえば以下のようになる。
| PATH_INFO | 実ファイルの場所 |
|---|---|
| /assets/application.js | app/assets/javascripts/application.js |
| /assets/models/project.js | app/assets/javascripts/models/project.js.coffee |
| /assets/style.js | app/assets/stylesheets/style.js |
要するに、
- ブラウザで
/assets/application.jsにアクセス - →
app/assets/javascripts/application.jsを探す - →
app/assets/javascripts/application.js.coffeeなどを探す - →
app/assets/stylesheets/application.jsなどを探す - →
app/assets/stylesheets/application.js.sassなどを探す - → Load Path にあるだけ繰り返す
- → (
public/assets/application.jsなどを探す) - どこにもなければ 404
ということ。
これだけではなく、CoffeeScript, Sacc/Scssといった各種エンジンのプロセス、ヘッダの適切な付与、キャッシュ、圧縮、//= require foo といったディレクティブの展開……、と言ったことも一手に引き受ける。
Rackベースのアプリケーション – 例えば Sinatra – で使う
以下のようなファイル構成とする。
$ tree . . ├── Gemfile ├── Gemfile.lock ├── app/ │ ├── javascripts/ │ │ └── application.js.coffee │ └── views/ │ └── index.haml ├── app.rb ├── config.ru └── public/
Gemfile:
1 2 3 4 5 6 | source :rubygems gem 'sinatra' gem 'haml' gem 'coffee-script' gem 'sprockets', '~> 2.0' |
config.ru:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $LOAD_PATH << File.expand_path(".") require 'rubygems' require 'bundler' Bundler.setup Bundler.require require 'app' map '/assets' do environment = Sprockets::Environment.new environment.append_path 'app/javascripts' run environment end map '/' do run App end |
Sprockets::EnvironmentとAppは別のアプリケーションであるため、別々にマウントする。
app.rb:
1 2 3 4 5 6 7 | class App < Sinatra::Base set :public_folder, "public" set :views, "app/views" get "/" do haml :"index" end end |
index.haml:
1 2 3 4 5 6 7 8 | !!! 5
%html
%head
%title Hello Sprockets
%body
%h1 Hello
%p hi
%script{:type => "text/javascript", :src => "assets/application.js"} |
/assets/application.jsを読み込ませにいく。これが、実ファイルapp/javascripts/application.js.coffeeと対応する
application.js.coffee:
1 | document.write "Hi, coffee" |
- 関数は一緒。
rackup し、 http://localhost:9292 を見てみると、確かに
JavaScriptが実行されている。
application.js.coffee は以下のように展開されているというわけだ:
1 2 3 | (function() { document.write("Hi, coffee"); }).call(this); |
ここで、CoffeeScriptを以下のように変更、追加すれば、
application.js.coffee:
1 2 3 | #= require countup document.write "Hi, coffee" |
同じフォルダに countup.js.coffee:
1 2 3 | for i in [1..5]
do (i) ->
document.write "count" + i + "<br />" |
こうなる。
忘れがちだが、 #= require などはファイルの先頭にあるディレクティブしか展開されない。
あとはじゃんじゃんバリバリと CoffeeScript を書いていこう。
さらに楽するために – Padrino::Sprockets
padrino-sprockets というシンプルな gem がある。簡単なクラスマクロを定義して、より楽にアセットパイプラインを利用できるようになる。ただし、素の Sinatra で利用する際には、 rubygems にホストされている 0.0.1 は不都合なので、 edge 版を使う。 0.0.2 からは何も考えず使えるといいですね……。
1 | gem 'padrino-sprockets', :git => "https://github.com/nightsailer/padrino-sprockets.git", :require => "padrino/sprockets" |
app.rb を以下のようにする。
1 2 3 4 5 6 7 8 9 10 | class App < Sinatra::Base register Padrino::Sprockets sprockets set :public_folder, "public" set :views, "app/views" get "/" do haml :"index" end end |
そして、 padrino-sprockets は assets のロードパスとして、
#{root}/assets/javascripts
#{root}/assets/images
#{root}/assets/stylesheets
を決め打ちするという一種の規約があるので、それにしたがう必要がある。この辺もう少し柔軟にしたければ、 pull request などをするとよいのでは。なお、 root は、 Sinatra であればデフォルトはそのアプリが定義されたファイルのあるディレクトリとなる。
具体的な作業としては、 app/javascripts にある CoffeeScript スクリプトを、 assets/javascripts と言うディレクトリを作ってその先にコピーしよう。
次に:
1 2 | bundle update
bundle exec rackup |
以上を実行すれば、同じような実行結果を見ることができるはずだ。
併せて
ただし、 1.0 系列の解説であることに注意。
10/28 もう一点追記。
「どうして」「どういうときに」高速になるかが分かると思います。






