Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Sprockets as a standalone service for a PHP application

I would like to duplicate the Rails asset pipeline feature in my Zend Framework PHP project. I think that it's possible to use the Sprockets gem as a standalone service but I am not sure how to configure it properly. I'm not interested in porting Sprockets to PHP, nor using a PHP port of Sprockets. The Sprockets rubygem already has everything I need. I just need to figure out how to set it up in a non-ruby environment.

Update: I have figured out how to run Sprockets as a Rack application. Now I'm interested in the differences between development and production environments. How does the Rails view helper generate all the <link> and <script> tags in development and fingerprint a single file in production?

like image 734
Andrew Avatar asked Jun 29 '12 19:06

Andrew


Video Answer


1 Answers

You're probably just going to have to dig into the source for Sprockets and Sprockets integration with Rails in order to really come up with a good solution for your problem, but I hope some of these pointers will help.

First, check out Sprockets::Helpers::RailsHelper#javascript_include_tag:

1  def javascript_include_tag(*sources)
2    options = sources.extract_options!
3    debug = options.key?(:debug) ? options.delete(:debug) : debug_assets?
4    body  = options.key?(:body)  ? options.delete(:body)  : false
5    digest  = options.key?(:digest)  ? options.delete(:digest)  : digest_assets?
6
7    sources.collect do |source|
8      if debug && asset = asset_paths.asset_for(source, 'js')
9        asset.to_a.map { |dep|
10         super(dep.pathname.to_s, { :src => path_to_asset(dep, :ext => 'js', :body => true, :digest => digest) }.merge!(options))
11       }
12     else
13       super(source.to_s, { :src => path_to_asset(source, :ext => 'js', :body => body, :digest => digest) }.merge!(options))
14     end
15   end.join("\n").html_safe
16 end

At a high level, this method does the following:

  1. Determine whether to concatenate everything into a single file or include all assets individually (line 3).
  2. Determine whether we should include the digest string in the asset filename (line 5).
  3. For each given source file, retrieve the Sprockets::Asset object corresponding to that source file (line 8).
  4. If we're debugging, call the superclass method with each Asset required by this one. Sprockets::Asset#to_a returns such an array (lines 9–10).
  5. If we're not debugging (or if we fail to retrieve an Asset object for some reason), call the superclass method with the top-level Asset (or the source filename as a string) (line 13).

Many of those methods are pretty simple and only depend on the environment you set up. For example, digest_assets?:

def digest_assets?
  Rails.application.config.assets.digest
end

Some of this configuration is saved in Rails.application.assets, which itself is a Sprockets::Environment object. You can actually play with this on the Rails console to get familiar with it (I'd highly recommend the awesome_print gem if you aren't already familiar with it):

1.9.3p194 :001 > Rails.application.assets.class
Sprockets::Environment < Sprockets::Base
1.9.3p194 :002 > Rails.application.assets['application.js'].class
Sprockets::BundledAsset < Sprockets::Asset
1.9.3p194 :003 > Rails.application.assets['application.js'].to_a.map(&:digest)
[
    [ 0] "6bb424b2409c6a5fb28acd15cc184b16",
    [ 1] "0ff3e5680ead3dadeee021c144835311",
    [ 2] "4c908739f93e83bda6b5e84f7ab10a29",
    [ 3] "319003f54b9408b4e41b0199e1848423",
    [ 4] "3f52cd966b6bb99a8f7994f5dcd7767f",
    [ 5] "c50a6aac16f6a69deeb722fe51e36c54",
    # ...
]

So essentially, Sprockets is responsible for determining dependencies, concatenation, and digesting of your assets, and Rails just ties it together with its helpers. It looks like you should be able to replicate this behavior in your framework in a reasonably straightforward manner.

like image 144
Brandan Avatar answered Oct 13 '22 00:10

Brandan