I'm using the function for caching multiple javascript files into one:
<%= javascript_include_tag :all, :cache => true %>
The way I understand it this creates the all.js file the first time a HTML file using it is generated.
But if the app is configured to use an asset host on a seperate server that does not deliver HTML the file will not be created. Is there a way to generate all.js manually on deploy?
You need to configure your deploy task in order to compress and create the file.
If you use Capistrano, you can add a callback to be executed on deploy.
Otherwise, the are a couple of alternatives that offers also a more efficient solution. The standard Rails strategy only merges all files into a single one. But you can gain additional benefit by compressing and minifying the final result. For more information you can read the GitHub asset deployment strategy or the Jammit documentation.
A great project for javascript concatenation is sprockets, which can be found here: http://getsprockets.org/
It's really easy to setup and integrate with capistrano. Might be worth a look.
Related
I'm working on using a Grunt workflow to manage my assets in my Rails app rather than Sprockets.
So far, I have my apps JS and CSS both being concatenated and minified into public/assets/javascripts/application.js and public/assets/stylesheets/application.css respectively.
And also have my Bower components JS and CSS being concatenated and minified into public/assets/javascripts/vendor.js and public/assets/stylesheets/vendor.css respectively.
Fonts and Images from Bower components are then copied into public/assets/(images|fonts).
This is all well and good but now I need the references to fonts/images within those files to be updated to reflect their new location.
I have looked at cssmin and yes it rewrites file references but I cannot get the file path to change depending upon the type of file being referenced.
Any ideas on how I can do this?
Also, I ahve been reading about Grunt plugins which can read your view files and use those to minify and concatenate files and update the and tags in the views for you.
Surely I can't do that in a Rails app? Is there a way I can deal with this in Rails?
This other StackOverflow post may be of help:
Integrate Grunt into Rails asset pipeline
The accepted answer recommends using the Half Pipe gem.
The second answer linked to a blog post about a Do-It Yourself solution: Goodbye, Sprockets! A Grunt-based Rails Asset Pipeline.
I haven't used either solution, but they are worth a try.
I wish to try out Grunt so for a task I have duplicated a project and want to convert it from using the default asset pipeline to work all via Grunt and it's tasks.
I can then evaluate both approaches and go for what I think turns out the best.
I have disabled the pipeline in my application.rb file. I have set up my Gruntfile.js and want to first of all get it to concatenate my javascript files. I am using the grunt-contrib-concat task but what I cannot figure out is the best place to tell grunt to place the processed files?
Would it be in /public? I am just confused as to where these files will now be served from? I know that I cannot use the Rails asset helpers in my views and will have to reference them myself, but from where?
I hope you can help.
Hey! I was watching the RailsCasts on Formtastic and he cached all of the files into one file this way:
<%= stylesheet_link_tag 'application', 'formtastic', 'formtastic_changes', :cache => "base" %>
This made it so all of the css files would be read into one big file which is base.css now but are still split up in development i believe.
How far can this go, can you have any amount of style sheets and put them in one file this way during production mode? Is this practice OK?
Yes, you can use this to concatenate any amount of files and it is good for use in production when you want to reduce requests to the server. This has been enhanced in Rails 3.1 with the introduction of the asset pipeline and new features related to it.
Also, this is a good practice in production because you generally want to keep things as small as possible for speed and performance and this includes asset requests to the server. You might want to look into minification for production as well, this strips any whitespace as well as comments and would help you serve up smaller files.
I'm attempting to use Jammit for packaging CSS and JS for a Rails app deployed on Heroku, which doesn't work out of the box due to Heroku's read only file system. Every example I've seen of how to do this recommends building all the packaged asset files in advance. Because of Heroku's Git-based deployment, this means you need to make a separate commit to your repository every time these files change, which is not an acceptable solution to me. Instead, I want to change the path that Jammit uses to write the cached packages to #{Rails.root}/tmp/assets (by changing ActionController::Base#page_cache_directory), which is writable on Heroku.
What I don't understand is how the cached files will be used without hitting the Rails stack every time, even using the default path for cached packages. Let me explain what I mean:
When you include a package using Jammit's helper, it looks something like this:
<%= include_javascripts :application %>
which generates this script tag:
<script src="/assets/application.js" type="text/javascript"></script>
When the browser requests this URL, what actually happens is that it gets routed to Jammit::Controller#package, which renders the contents of the package to the browser and then writes a cached copy to #{page_cache_directory}/assets/application.js. The idea is that this cached file is built on the first request, and subsequent requests should serve the cached file directly without hitting the Rails stack. I looked through the Jammit code and I don't see how this is supposed to happen. What prevents subsequent requests to /assets/application.js from simply routing to Jammit::Controller again and never using the cached file?
My guess is that there's a Rack middleware somewhere I'm not seeing that serves the file if it exists and forwards the request on to the controller if it doesn't. If that's the case, where is that code? And how would it work when changing ActionController::Base#page_cache_directory (effectively changing where Jammit writes cached packages)? Since #{Rails.root}/tmp is above the public document root, there's no URL that maps to that path.
Great question! I haven't set this up myself, but it's something I've been meaning to look into, so you've prompted me to do so. Here's what I would try (I'll give a shot myself soon, but you are probably going to beat me to it).
config.action_controller.page_cache_directory = "#{Rails.root}/tmp/page_cache"
Now change your config.ru to:
require ::File.expand_path('../config/environment', __FILE__)
run Rack::URLMap.new(
"/" => Your::App.new,
"/assets" => Rack::Directory.new("tmp/page_cache/assets"))
Just make sure not to have anything in public/assets, since that won't ever be picked up.
Notes:
This is for Rails 3. Not sure of the solution under Rails 2.
It looks like Rack::Directory sets cache control headers to 12 hours so Heroku will cache your assets to Varnish. Not sure if Jammit sets this in its controller, but even if it doesn't, it will be cached quite quickly.
Heroku also sets ENV['TMPDIR'] now as well, so you can use that instead of Rails.root + '/tmp' if you wish.
This might be of use, it's for a different gem but the idea is similar and I'm trying to get it working with the plain asset helpers.
http://devcenter.heroku.com/articles/using-compass
Unfortunately it seems to be quite difficult to get rails to do this without patching/rewriting the asset helpers module (which resembles coupled spaghetti).
I am building a Facebook App which is heavy on Javascript. For this I have multiple Javascript files. Since in Facebook development, the page is served over a tunnel, there is excessive latency added while requesting multiple javascript files. Is it possible to combine the contents of multiple javascript files at runtime? Having multiple files makes it easy to develop, and hence I am avoiding having to combine it while development itself.
You can pass a :cache option to the javascript_include_tag which will combine the files into one:
<%= javascript_include_tag :all, :cache => true %>
Note that this depends on ActionController::Base.perform_caching being set to true, which it is by default for the Rails production environment.
See http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#M001493
in your config file for the environment located at /config/environments, you have a file for each, like development.rb and so on.
In that file, you can set config.assets.debug = false
and that will reduce files down to 1 js file, and 1 css file.
Better than combining at runtime, have a look at Frizione. It's a framework that will allow you to combine your javascript files at deploy time, and compress them. So you get to save all around. It throws in doc generation and JSLint checking as well, but that's just an added bonus.
Jammit is a good catch too, to combile js and css files.
http://documentcloud.github.com/jammit/
I've used the asset_packager gem to do this in my applications.
It will combine and minimize your javascript (and CSS) files for production and adds some view helpers that make it very easy to use. There's a rake command that you run to generate the packaged files if the originals have changed.