# RequireJS for Rails
Integrates [RequireJS](http://requirejs.org/) into the Rails 3 Asset Pipeline.
**UPGRADE NOTES:** Users upgrading within the 0.x series should read the Changes section for relevant usage changes. We're pushing hard to 1.0, when the configuration and setup details will be declared stable. Until that time expect some bumps as things bake out.
## Usage
1. Add this to your Rails app's `Gemfile`:
```
gem 'requirejs-rails'
```
2. Remove all Sprockets directives such as `//= require jquery` from `application.js` and elsewhere. Instead establish JavaScript dependencies using AMD-style `define()` and `require()` calls.
3. Use `requirejs_include_tag` at the top-level of your app's layout(s). Other modules will be pulled in dynamically by `require.js` in development and for production builds optimized by `r.js`. Here's a basic `app/views/layouts/application.html.erb` modified for `requirejs-rails`:
```erb
Frobnitz Online
<%= stylesheet_link_tag "application" %>
<%= requirejs_include_tag "application" %>
<%= csrf_meta_tags %>
<%= yield %>
```
4. Organize your JavaScript or CoffeeScript code into modules using `define()`:
```coffeescript
# app/assets/javascripts/views/tweet_view.js.coffee
define ['backbone'], (Backbone) ->
class TweetView extends Backbone.View
# ...
```
5. Instantiate your app using `require()` from a top-level module such as `application.js`:
```coffeescript
# app/assets/javascripts/application.js.coffee
require ['jquery', 'backbone', 'TheApp'], ($, Backbone, TheApp) ->
# Start up the app once the DOM is ready
$ ->
window.App = new TheApp()
Backbone.history.start
pushState: true
window.App.start()
```
6. When ready, build your assets for production deployment as usual.
`requirejs-rails` defaults to a single-file build of `application.js`.
Additional modules and r.js layered builds may be specified via
`config\requirejs.yml`; see the Configuration section below.
```rake assets:precompile```
## Configuration
### The Basics
Configuration lives in `config/requirejs.yml`. These values are inspected and
used by `requirejs-rails` and passed along as configuration for require.js and
`r.js`. The default configuration declares `application.js` as the sole
top-level module. This can be overridden by creating
a `config/requirejs.yml`, such as:
```yaml
modules:
- name: 'mytoplevel'
```
You may pass in [require.js config
options](http://requirejs.org/docs/api.html#config) as needed. For example,
to add path parameters:
```yaml
paths:
d3: "d3/d3"
"d3.time": "d3/d3.time"
```
### Layered builds
Only modules specified in the configuration will be created as build artifacts
by `r.js`. [Layered r.js
builds](http://requirejs.org/docs/faq-optimization.html#priority) be
configured like so:
```yaml
modules:
- name: 'appcommon'
- name: 'page1'
exclude: ['appcommon']
- name: 'page2'
exclude: ['appcommon']
priority: ['appcommon']
```
In this example, only modules `page1` and `page2` are intended for direct
loading via `requirejs_include_tag`. The `appcommon` module contains
dependencies shared by the per-page modules. As a guideline, each module in
the configuration should be referenced by one of:
- A `requirejs_include_tag` in a template
- Pulled in via a dynamic `require()` call. Modules which are solely
referenced by a dynamic `require()` call (i.e. a call not optimized by r.js)
**must** be specified in the modules section in order to produce a correct
build.
- Be a common library module like `appcommon`, listed in the `priority` config
option.
### Almond support
This gem supports single-file builds with
[almond](https://github.com/jrburke/almond). Use the following setting in
`application.rb` to enable it:
```ruby
config.requirejs.loader = :almond
```
Almond builds have the restriction that there must be exactly one modules entry in
`requirejs.yml`. Typically the [wrap option](https://github.com/jrburke/r.js/blob/master/build/example.build.js#L275) will be used to create a self-contained build:
```yaml
modules:
- name: 'main'
wrap: true
```
### Build-time asset filter
The `requirejs-rails` build process uses the Asset Pipeline to assemble assets
for the `r.js` build. By default, assets ending in `.js`, `.html`, and `.txt`
will be made available to the build. If you have other asset suffixes to
include, use the `logical_asset_filter` config setting to add them.
For example, if your templates all end in `.templ` like so...
```javascript
// in app/assets/javascripts/myapp.js
define(function (require) {
var stuff = require('text!stuff.templ');
// ...
});
```
... then this config setting will ensure they're picked up in the build:
```ruby
# in config/application.rb
config.requirejs.logical_asset_filter += [/\.templ$/]
```
## Advanced features
### Additional data attributes
`requirejs_include_tag` accepts an optional block which should return a hash.
This hash will be used to populate additional `data-...` attributes like so:
```erb
<%= requirejs_include_tag "page1" do |controller|
{ 'foo' => controller.foo,
'bar' => controller.bar
}
end
%>
```
This will generate a script tag like so:
```
```
## Using AMD libraries
I currently recommend placing your AMD libraries into `vendor/assets/javascripts`. The needs of a few specific libraries are discussed below.
### jQuery
jQuery users must use jQuery 1.7 or later (`jquery-rails >= 1.0.17`) to use it as an [AMD module](http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition) with RequireJS. To use jQuery in a module:
```coffeescript
# app/assets/javascripts/hello.js
define ['jquery'], ($) ->
(id) ->
$(id).append('hello!
')
```
### Backbone.js
Backbone 0.9.x doesn't support AMD natively. I recommend the [amdjs
fork of Backbone](https://github.com/amdjs/backbone/) which adds AMD
support and actively tracks mainline.
### Underscore.js
Underscore 1.3.x likewise doesn't have AMD support. Again, see
the [amdjs fork of Underscore](https://github.com/amdjs/underscore).
## 0.x API Changes
Usage changes that may break functionality for those upgrading along the 0.x
series are documented here. See [the Changelog](https://github.com/jwhitley/requirejs-rails/blob/master/CHANGELOG.md) for the full
list of feature additions, bugfixes, etc.
### v0.5.1
- `requirejs_include_tag` now generates a data-main attribute if given an argument, ala:
```erb
<%= requirejs_include_tag "application" %>
```
This usage is preferred to using a separate
`javascript_include_tag`, which will produce errors from require.js or
r.js if the included script uses define anonymously, or not at all.
### v0.5.0
- `application.js` is configured as the default top-level module for r.js builds.
- It is no longer necessary or desirable to specify `baseUrl` explicitly in the configuration.
- Users should migrate application configuration previously in `application.js` (ala `require.config(...)`) to `config/requirejs.yml`
## TODOs
Please check out [our GitHub issues page](https://github.com/jwhitley/requirejs-rails/issues)
to see what's upcoming and to file feature requests and bug reports.
----
Copyright 2011 John Whitley. See the file MIT-LICENSE for terms.