Friday, February 20th, 2009

Sprockets: Build time JavaScript dependancy management

Category: JavaScript, Ruby, Utility

<p>

Sprockets is a build time Ruby tool that reads in your JavaScript files, preprocesses and concatenates:

It takes any number of source files and preprocesses them line-by-line in order to build a single concatenation. Specially formatted lines act as directives to the Sprockets preprocessor, telling it to require the contents of another file or library first or to provide a set of asset files (such as images or stylesheets) to the document root. Sprockets attempts to fulfill required dependencies by searching a set of directories called the load path.

It is created by Sam Stephenson, and he tells us why you may be interested to use it:

  • Extract reusable code and share it across multiple web sites or applications.
  • Speed up your site by automatically concatenating JavaScript into one file.
  • Organize your JavaScript source code into multiple commented files and directories.
  • Use bleeding-edge framework and library code in your application.
  • Sprockets is documentation-friendly

The preprocessor uses a require/provide pattern (Dojo has dojo.require(), dojo.provide() and can do build time and runtime work):

require

Use the require directive to tell Sprockets that another JavaScript source file should be inserted into the concatenation before continuing to preprocess the current source file. If the specified source file has already been required, Sprockets ignores the directive.

The format of a require directive determines how Sprockets looks for the dependent source file. If you place the name of the source file in angle brackets:

//= require <prototype>

Sprockets will search your load path, in order, for a file named prototype.js, and begin preprocessing the first match it finds. (An error will be raised if a matching file can’t be found.) If you place the name of the source file in quotes:

//= require "date_helper"

Sprockets will not search the load path, but will instead look for a file named date_helper.js in the same directory as the current source file. In general, it is a good idea to use quotes to refer to related files, and angle brackets to refer to packages, libraries, or third-party code that may live in a different location.

You can refer to files in subdirectories with the require directive. For example:

//= require <behavior/hover_observer>

Sprockets will search the load path for a file named hover_observer.js in a directory named behavior.

provide

Sometimes it is necessary to include associated stylesheets, images, or even HTML files with a JavaScript plugin. Sprockets lets you specify that a JavaScript source file depends on a set of assets, and offers a routine for copying all dependent assets into the document root.

The provide directive tells Sprockets that the current source file depends on the set of assets in the named directory. For example, say you have a plugin with the following directory structure:

plugins/color_picker/assets/images/color_picker/arrow.png
plugins/color_picker/assets/images/color_picker/circle.png
plugins/color_picker/assets/images/color_picker/hue.png
plugins/color_picker/assets/images/color_picker/saturation_and_brightness.png
plugins/color_picker/assets/stylesheets/color_picker.css
plugins/color_picker/src/color.js
plugins/color_picker/src/color_picker.js

Assume plugins/color_picker/src/ is in your Sprockets load path. plugins/color_picker/src/color_picker.js might look like this:

//= require "color"
//= provide "../assets"

When <color_picker> is required in your application, its provide directive will tell Sprockets that all files in the plugins/color_picker/assets/ directory should be copied into the web server’s document root.

Build time constant replacement

You may need to parameterize and insert constants into your source code. Sprockets lets you define such constants in a special file called constants.yml that lives in your load path. This file is formatted as a YAML hash.

Continuing the color_picker example, assume plugins/color_picker/src/constants.yml contains the following:

javascript
< view plain text >
  1. COLOR_PICKER_VERSION: 1.0.0
  2. COLOR_PICKER_AUTHOR: Sam Stephenson <sam @example.org>

The constants are specified in a single place, and you can now insert them into your source code without repetition:

javascript
< view plain text >
  1. /* Color Picker plugin, version < %= COLOR_PICKER_VERSION %>
  2.  * (c) 2009 < %= COLOR_PICKER_AUTHOR %>
  3.  * Distributed under the terms of an MIT-style license */
  4.  
  5. var ColorPicker = {
  6.   VERSION: '< %= COLOR_PICKER_VERSION %>',
  7.   ...
  8. };

The resulting concatenated output will have the constant values substituted in place:

javascript
< view plain text >
  1. /* Color Picker plugin, version 1.0.0
  2.  * (c) 2009 Sam Stephenson </sam><sam @example.org>
  3.  * Distributed under the terms of an MIT-style license */
  4.  
  5. var ColorPicker = {
  6.   VERSION: '1.0.0',
  7.   ...
  8. };

Constants share a global namespace, so you can refer to constants defined anywhere in your load path. If a constant is not found, Sprockets raises an error and halts further preprocessing.

Related Content:

Posted by Dion Almaer at 12:01 am
3 Comments

+++--
3.4 rating from 30 votes

3 Comments »

Comments feed TrackBack URI

Good to see Sam is still contributing to his own framework. Prototype just switched to using Sprockets.

Comment by Jadet — February 19, 2009

Can you extend the building process with additionnal commands ?
Like passing the file into jsmin/jslint and commiting to a CSV/SVN ?

Is there also a way to bundle it in a portable (no-install) package so it can be easily deployed using the versioning server ?

Comment by ywg — February 20, 2009

I have a question regarding Prototype and Sprockets. Do you think it would be possible using Sprockets to create custom builds of Prototype, removing what I don’t use?

Say for example I never use Ajax in my app, can I simply remove the related require in prototype.js altogether and get a working trimmed down version of the library?

Comment by VeejayRampay — March 9, 2009

Leave a comment

You must be logged in to post a comment.