Skip to content

hyperstudio/repertoire-assets

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Repertoire Assets 
=================

Repertoire Assets is software for developing and distributing Javascript and
CSS components for re-use in ruby web projects. It helps you manage large
javascript codebases by dividing code among many files, and allows you to
publish your javascript libraries (and their css and images) via ruby gems.
You can then require them in other javascript web applications, and the asset
software will manage any dependencies among the libraries so that you can
focus on writing your own code.

While you're developing, the Repertoire middleware ensures that any javascript
and css you've required appear seamlessly in your own application's url space--
even though they're loaded from elsewhere. You can step through javascript
code file by file, just as it appears in your application and gems. When a
javascript source file changes, it is reloaded automatically and its
dependencies re-analyzed.

Finally, when you have packaged your app for production use, the asset
software bundles and compresses javascripts and stylesheets, and copies any
associated binary assets into your application's public directory. This way,
all the assets will be served directly by your web server, only one compressed
javascript and one css file are downloaded to the client. This yields a much
more responsive user experience.

If you want to distribute your javascript component for use in non-ruby frame-
works, repertoire assets can also be used to build and bundle the files.  This
gives you the flexibility of developing and deploying components easily for use
within ruby frameworks, but also distributing your code to a wider audience.



*Architecture*

The software consists of two components:

(1) A preprocessor that assembles javascript based on dependencies in your
code, much like C's #include directive or ruby's "require" method. For
example, you could require the "shapes" javascript library from a ruby gem by
including '//= require <shapes>' your javascript source. The preprocessor will
find the library and load it and its depedencies into your web page before
your own code, in the proper order. If a given code library has already been
sourced, it is not loaded again.

This is accomplished by compiling an ordered manifest of all the javascript
files required by your code, and then inserting the appropriate <script> and
<link> tags into your pages' html. Because it uses a rack filter, the system
is largely transparent to your application. Whether it's written in Rails,
Merb, Sinatra, or another ruby web framework, the javascript and css will
still work.


(2) A pair of rack filters: one that intercepts http requests for assets in
the manifest and serves them directly, and another that inserts the manifest
into html pages right before they are served. In a production environment, the
filters collect all of your application's required assets, compress those they
can, and cache them in your application's public asset directory.



*Preparing your application*

You can use javascript components packaged with Repertoire Assets in any ruby
web application based on Rack (this includes Rails, Merb, Sinatra and others).

The javascript gem libraries can either be bundled with your application, or
reside in the system rubygems repository. Likewise, the repertoire-assets gem
may be in either place.

For Rails 3.0, no configuration is necessary for development use.  Production
environments require a single line of configuration.  See the INSTALL file
for details.



*Importing Javascript Libraries and Files*

Repertoire-assets works by scanning a set of javascript source files in your
application on startup and locating any required libraries (and their
dependents) on the ruby load path. In development mode, the files will be
re-scanned whenever a dependency is modified.

Files are sourced in the following order:

  <app>/public/javascripts/application.js
  <app>/public/javascripts/*.js

In these files, you can use preprocessor directives similar to C's:

  //= require <shapes>                         /* search for a library shapes.js in gems load path */
  //= require "drawing/scene"                  /* load ./drawing/scene.js relative to the current file */
  //= require "../stylesheets/red-theme.css"   /* load css relative to the current file */

The relevant <script> and <link> tags for any file you 'require' are added to
your application's outgoing html automatically. Any dependencies are added
in logical order.



*Structuring Your Application's Javascript*

It's best to establish a layout similar to most ruby or C code, where files
require any dependencies at their head and a single application file starts
everything off.

For example, a paint application might look like:

  <app>/public/javascripts/application.js:
    //= require "drawing/scene"
    //= require "accounts/user"
    ...
  <app>/public/javascripts/drawing/graph.js
  <app>/public/javascripts/drawing/scene.js:  
    //= require "graph"
    ...
  <app>/public/javascripts/accounts/user.js

The asset preprocessor will figure out what order to load files, so you don't
have to. But when you debug using Firebug or Webkit, your code will still
appear in the file layout you're used to rather than jumbled together
(something other javascript asset bundlers commonly do).



*Developing Javascript and CSS Gem Components*

Repertoire assets javascript libraries are ordinary rubygems packages. Say
you wanted to create a javascript drawing package to support the painting
application above. Here is the suggested gem source structure:

  superdraw/README
  superdraw/Rakefile                                    # see below
  superdraw/superdraw.gemspec                           # generated by Rakefile
  superdraw/lib/superdraw.rb                            # empty file (required for rubygems)
  superdraw/public/javascripts
  superdraw/public/javascripts/superdraw.js             # the superdraw library file
  superdraw/public/javascripts/superdraw/circle.js
  superdraw/public/javascripts/superdraw/polyhedron.js
  superdraw/public/javascripts/superdraw/square.js
  superdraw/public/stylesheets/superdraw.css            # required css
  superdraw/public/images/superdraw/anchor.png          # provided image assets 
  superdraw/public/images/superdraw/crosshairs.png
  superdraw/LICENSE
  superdraw/TODO

As you can see, a Javascript component gem has the same structure as a Rails
or Merb application. You may also include ruby library code in lib/ if you wish.

The asset loader will find any library in $LOAD_PATH/../public/javascripts/*.js,
in this case 'superdraw.js'.  This file might look something like the following:

  //= require "superdraw/circle"                      # load private source files
  //= require "superdraw/polyhedron"
  //= require "superdraw/square"
  //= require "../stylesheets/superdraw.css"          # the library's main css file
  //= provide "../images/splashscreen.jpeg"           # ancillary assets
  //= provide "../images/superdraw/**/*"

If the circle, polyhedron or square files use other javascript libraries --
say, the Processing javascript framework -- they will include require
directives of their own.

The provide directive is used to specify additional assets that should be
available in the host application's url space. You can reference these files
in your css, and any relative urls will be rewritten appropriately when the
css files are bundled together and moved to a new location in the host app.

Unix-style file globs can be used in any require or provide statement, as seen
in the final provide statement above. Also, you can combine search and
relative file paths to load sub-libraries (e.g. 'require <superdraw/circle>').

Keep in mind that files under /public may appear in your host app's URL
space. Hence, it is advantageous to namespace your materials in directories
named after your library (e.g. /images/superdraw/circle.png rather than
/images/circle.png).

For security reasons, the system will never serve a file that was not
explicitly required or provided.

If you are using Rails and would like to preview the manifest or generate
digests by hand, use 'rake assets:list' and 'rake assets:build'.



*Debugging Javascript Dependencies*

When your web application starts up, the asset manager logs a record of which
javascript and css files have been required, by which libraries, and what url
each is served at.  For example:

~ Requiring /javascripts/application.js (/Users/yorkc/facet-example-app/public/javascripts/application.js)
~ Requiring   /stylesheets/master.css (/Users/yorkc/facet-example-app/public/stylesheets/master.css)
~ Requiring   /javascripts/rep.faceting.js (repertoire_faceting-0.3.4)
~ Requiring     /javascripts/jquery.js (jquery-1.3.2)
~ Requiring       /javascripts/jquery/jquery-1.3.2.js (jquery-1.3.2)
~ Requiring     /stylesheets/rep.faceting.css (repertoire_faceting-0.3.4)
~ Providing     /images (repertoire_faceting-0.3.4)
~ Requiring   /javascripts/rep.protovis-facets.js (repertoire_faceting-0.3.4)
~ Requiring     /javascripts/protovis.js (repertoire_faceting-0.3.4)
~ Requiring       /javascripts/protovis/protovis-d3.1.js (repertoire_faceting-0.3.4)
~ Assets processed: 1 source files, 5 libraries available, 10 assets provided, 9 files in manifest

Requiring a file that cannot be found is a fatal error, as in Ruby or C. If
two libraries are found that satisfy a requirement, you will be informed of
the conflict and told which one is being used.


*Deployment Options*

The following options are available for production configurations.

   - precache [false]                   # copy and bundle assets into host application?
   - compress [false]                   # compress bundled javascript & stylesheets? (implies :precache)
   - disable_rack_assets [false]               # don't interpolate <script> and <link> tags
   - path_prefix     ['']                      # prefix for all generated urls

In general, 'compress' is preferred. This copies all binary assets into
your host application, bundles together all required javascript and css into
files named '/digest.js' and '/digest.css', and compresses these files using
YUI compressor.  Use 'precache' if you do not want to compress the files.

In both cases, the asset mirroring middleware is disabled, and your app's
webserver serves all assets directly from the filesystem.

If desired, you may also disable the <script> and <link> middleware in your
production install while still precaching and compressing all assets. Set the
'disable_rack_assets' configuration option to true, and add the following to
your html header:

<link rel='stylesheet' type='text/css' href='/digest.css'/> 
<script language='javascript' type='text/javascript' src='/digest.js'></script>

Note, however, that the server performance gain from 'disable_rack_assets' is
minimal.

About

Javascript asset compilation and distribution framework for Rails

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages