WEBサービス創造記

WEBサービスを作ったり保守したりしてる人のメモブログです。

Sprocketsについて復習する

   

Sprocketsの概要

Railsではアセットファイル(JS, CSS, 画像などWebサイトの直接のレスポンスではないもの)を効率的に管理するためにAsset Pipelineという枠組みを提供している。

Sprocketsは、そのAsset Pipelineの基盤となるgem。
Rails3.1から導入された。

Sprocketsの役割

アセットパッケージング機能を提供。 具体的には下記など。

  1. アセットファイルへのパスの管理
  2. アセットファイルの圧縮
  3. アセットファイルの結合
  4. アセットファイル間の依存性の解決
  5. アセットファイルのコンパイル

パスの管理

Railsプロジェクトではアセットファイルの実体は"app/assets/stylesheets"や"app/assets/javascripts"などに置いてある。
このファイルへのリンクはstylesheet_link_tagjavascript_include_tagといったSprocketsが提供しているヘルパーメソッドによって行う。

例えば、Railsでデフォルトで作られるレイアウトファイルでは下記のようにコーディングされている。

  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>

development環境で、ブラウザでアプリにアクセスしてHTMLソースを閲覧すると、これは下記のように変換されている。

<link href="/assets/application.css?body=1" media="all" rel="stylesheet" />

このように"/assets"以下にアクセスが来た場合にSprocketsがリクエストを解釈して、適切なアセットをレスポンスしてくれるようになっている。
上記の場合は"app/assets/stylesheets/application.css"が返される。

もしSassなどのスタイルシート言語を使っている場合は"app/assets/stylesheets/application.css.scss"をコンパイルした結果を返してくれる(※config.assets.compile = trueの場合。詳しくは後述。)。

圧縮・結合

また、production環境では通信コストの軽減などの目的のため、予め圧縮・結合しておいたアセットを配置するのが一般的。

プリコンパイルは下記コマンドで実行できる。

rake assets:precompile

このコマンドにより、public/assets/以下に圧縮・結合されたアセットが配置される。
この処理はプリコンパイルと呼ばれ、大抵デプロイ時に実行される。

"public/assets/"に配置されたプリコンパイルされたアセットは静的ファイルとして提供される。これでリクエスト毎にいちいちコンパイルをしなくて済み、サーバ負荷が軽減される。

このプリコンパイルされたファイルのレスポンスもSprocketsがやってくれる。
具体的にはproduction環境のコンテキストでstylesheet_link_tagが解釈されると、プリコンパイルされたファイルへのlinkタグを出力してくれる。

この振る舞いは"config/environments/development.rb"などで設定されているconfig.assets.compileによる。
この値がfalseだと前述したようなプリコンパイルされたアセットを静的ファイルとして参照、trueだと、リクエスト毎に動的にコンパイルを行う。

productionではfalse、developmentだとtrueが既定値となっている。
development環境でもリクエスト毎に動的にコンパイルを行いたい場合は以下のように設定する。

config.assets.compile = false

依存性の解決

例えば、jQueryを利用したJavascriptを書いている場合は、先にjQueryを読み込んでおかないと動かないので、このようなコードはjQueryに依存していると言える。
このようなアセットファイル間で発生する依存性の解消は、requireディレクティブで解決する。

jQueryを読み込むには下記のように記載する。

//= require jquery

requireの他にも、指定されたディレクトリを再帰的に読み込むrequire_treeや指定されたファイルがrequireされた場合に無視するstubなどの複数のディレクトリがある。
application.cssやapplication.jsなどでこれらのディレクティブの記載が見られる。

前述したように、production環境ではアセットは結合して配置するのが一般的である。
この際アセット結合の仲介役となるようなファイルのことをマニフェストファイルといい、マニフェストファイルにはそのアプリでの全ての依存関係を示したディレクティブを記述する。

Sprocketsでは規約として、"application.css"、"application.js"という名前のファイル名がマニフェストファイルとして読み込まれるようになっている。
もし上記以外のファイルをプリコンパイルの対象としたいなら、"confg/environments/production.rb"などで以下のように指定する必要がある。

config.assets.precompile += %w(admin.js admin.css)

production環境ではstylesheet_link_tagjavascript_include_tagヘルパーは、プリコンパイルされたアセットへのリンクを出力する。
一方、development環境ではマニフェストファイルのディレクティブで解決された依存関係の順番にlinkタグやscriptタグで個別のファイルを展開していく。

この動作は"config/environments/development.rb"や"config/environments/production.rb"のconfig.assets.debug = trueで制御されている。
これがfalseなら前述した個別のファイルに展開する方式になり、trueならファイルは結合される。

前者はdevelopment環境の既定値で、後者はproductionの既定値。
developmentでも下記のように設定することでファイルの結合を行うようにすることができる。

config.assets.debug = true

コンパイル

例えば、CoffeeScriptなどのaltJSを利用している場合でもSprocketsがコンパイルしてくれる。
コンパイル処理自体は外部のコンパイラに移譲しているらしいのでそれらとファイルとの橋渡しをしてくれている。

Sprocketsはほとんどの場合、execJSインターフェースを経由してJSの実行環境を使いコンパイラを呼び出しているに過ぎません。
Ruby – Sprockets再考 モダンなJSのエコシステムとRailsのより良い関係を探す – Qiita

とりあえずここまで。

 - Ruby on Rails , , ,