Rails 3.1 asset pipeline and manually ordered Javascript requires

Ruby on-Rails-3Asset PipelineSprockets

Ruby on-Rails-3 Problem Overview


I am trying to convert an existing app to the new 3.1 asset pipeline layout, and want to include a lot of vendor files that have to be in a specific order, (underscore.js and backbone being one pair). As such, I can't just use a = require_tree . to pull in my vendor files, (without renaming each file with a prefix. Yuck).

The following is within my app/assets/javascripts/application.js file:

//= require modernizr-1.7
//= require jquery-1.6.1
//= require underscore-1.1.5
//= require backbone-0.3.3
//= require_tree .

I have tried every combination of with/out extensions, with/out the require_tree and with/out the relative paths, and nothing works. All of my vendor files are in /vendor/assets/javascripts/.

I feel like I am being stupid because this seems like such an obvious use case, (including specific files by name in an order is common with JS, no?) that I must be doing something idiotic?

Ruby on-Rails-3 Solutions


Solution 1 - Ruby on-Rails-3

You have two possible structure : the first one and the second one. With both following examples, you expose a package at /assets/externals.js. You can javascript_include_tag this package, but you can also require it in your application.js file.

The first one

vendor/
├── assets
│   ├── javascripts
│   │   ├── externals.js
│   │   ├── modernizr-1.7.js
│   │   └── underscore-1.1.6.js
│   └── stylesheets
└── plugins

The file externals.js contains :

//= require ./underscore-1.1.6.js
//= require ./modernizr-1.7.js

The second one

vendor/
├── assets
│   ├── javascripts
│   │   └── externals
│   │       ├── index.js
│   │       ├── modernizr-1.7.js
│   │       └── underscore-1.1.6.js
│   └── stylesheets
└── plugins

The file index.js contains :

//= require ./underscore-1.1.6.js
//= require ./modernizr-1.7.js

Solution 2 - Ruby on-Rails-3

You can require each file in particular order and then add:

//= require_self

instead of:

//= require_tree .

Solution 3 - Ruby on-Rails-3

My answer applies to Rails 3.1rc4, I don't know whether it functions the same with other versions.

You can actually put all require statements in app/assets/javascripts/application.js whether or not the .js files are in app/assets/javascripts/ or vendor/assets/javascripts/

Like so:

// this is in app/assets/javascripts/application.js

//= require modernizr-2.0
//= require jquery
//= require jquery_ujs
//= require jqueryui-1.8.12
//= require jquery.easing-1.3
//= require jquery.noisy
//= require jquery.jslide-1.0
//= require respond
//= require smoke
//= require_tree

I included require_tree here because I have other javascript files for my individual controllers (pages.js.coffee, users.js.coffee) and a general one for site-wide stuff (site.js.coffee)

Meanwhile here's the file structure.

app/
├── assets
│   ├── javascripts
│   │   ├── application.js
│   │   ├── pages.js.coffee
│   │   ├── users.js.coffee
│   │   └── site.js.coffee
│   └── stylesheets
└── plugins

vendor/
├── assets
│   ├── javascripts
│   │   ├── jquery.easing-1.3.js
│   │   ├── jquery.jslide-1.0.js
│   │   ├── jquery.noisy.js
│   │   ├── jqueryui-1.8.12.js
│   │   ├── modernizr-2.0.js
│   │   ├── respond.js
│   │   └── smoke.js
│   └── stylesheets
└── plugins

This allows me to control the load order of vendor libraries (which matters a lot, usually) and not worry about my internal javascript, where order generally matters less.

More importantly, I control all require statements within one often used file, I find that both safer and cleaner.

Solution 4 - Ruby on-Rails-3

I believe you can put a library.js in your in vendor/assets/javascripts and then simply

//= require library.js

from your application.js, no?

Solution 5 - Ruby on-Rails-3

require_tree does exactly what you tell it. If you give it

//= require_tree .

it loads the files in the current directory where require_tree is called. If you give it

//=require_tree ../../../vendor/assets/javascripts

then you'll get the javascript under vendor.

I did not like the ../../.. notation, so I created a file called vendor/assets/javascripts/vendor_application.js which contains:

//= require_tree .

That loads the javascript under the vendor directory.

Note, require does search the 3 pipeline locations (app, lib, vendor) for the file to require. require_tree is literal, which is probably the way it should be.

The railscast on this is very helpful: http://railscasts.com/episodes/279-understanding-the-asset-pipeline

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbesekuView Question on Stackoverflow
Solution 1 - Ruby on-Rails-3Romain TribesView Answer on Stackoverflow
Solution 2 - Ruby on-Rails-3martinciuView Answer on Stackoverflow
Solution 3 - Ruby on-Rails-3Olivier LacanView Answer on Stackoverflow
Solution 4 - Ruby on-Rails-3muxcmuxView Answer on Stackoverflow
Solution 5 - Ruby on-Rails-3justingordonView Answer on Stackoverflow