Rails 3.1 asset pipeline and manually ordered Javascript requires
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?
Solution 1:
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:
You can require each file in particular order and then add:
//= require_self
instead of:
//= require_tree .
Solution 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.