How many css files can you cache into one file in ruby on rails? - ruby-on-rails

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.

Related

rails 4.2 assets loading

I'm playing with a rails 4.2 application and it seems like it loads all of my stylesheets for each and every page.
Is that true? How is it better than loading for each page only the relevant stylesheets?
On one hand, I know they'll all be minified when going to production, and it will reduce the total size and cache one CSS for the whole website.
On the other hand, page I might have some thin pages that will need no more than a few css lines to be rendered correctly that will get tones of files for no reason. It will also require me to be super strict and safe when choosing class names in order to have no collisions and unwanted overrides.
What about JS assets? It acts the same way?
(I guess the answer for image assets is "hell no!")
Yes, in development you'll see a lot of files (all of them) and in production they will be compiled and minified to a single file.
Once this file has been downloaded by the client it will be cached and wont need to make any further requests to load other stylesheet files on concurrent request (unless caching and turbolinks has been disabled). The downside is that the file size will be larger and make the initial load time slightly longer.
One problem as you point out is scoping. In my experience it's way better to always apply proper scopes when developing. And in rails using sass it's really easy to have nice and tidy css.
The same goes for javascript, but not for images as you pointed out.
That said. There are ways to work around this if desired, but more often than not I've realized that there are more pros than cons with a single file.
Edit:
Oh, and if you're new to rails, beware that turbolinks might cause you some headaches in the beginning messing with page ready in js-files before you get the hang of it. But it's worth it in the end.
The advantage and rationale for this is to reduce the amount of data that is sent to the client after the first page load. The first page load pulls down all the js/css (compiled into single files), but then this can be cached and reduces the amount on each subsequent page load.
The following is purely theoretical, if at all possible, try and work with the defaults of one css/jss file
If you absolutely do want to trim it down, then you can. Your application.css manifest file (or js) probably includes a line such as:
//= require_tree .
which says, require everything in this directory. you could then split this down so application.css only requires everything in the application folder (absolutely need to know):
//=require_tree ./application
Then add additional manifest files, for example for an admin section, so that the admin styles/JS can be loaded only when needed in admin.js
//=require_tree ./admin
Then in your layout file you can do
= stylesheet_link_tag "application", media: "all"
= yield :additional_stylesheets
And where you want those additional styles you can add them.
- content_for :additional_stylesheets do
= stylesheet_link_tag "admin", media: "all"
end
Note: this will cause issues if you're using turbolinks.
Note II: You may need to add these to the precompile list in application.rb:
config.assets.precompile += ['additional_manifests.css']
You could modify this workflow to not include any CSS at all to start with and only load what you need.

Asset managing with Rails 3 (on Heroku) (Jammit, AssetHat, Rack PageSpeed)

I am interested in the pros and cons of the different tools for managing assets in Rails 3.0.x (especially on Heroku).
There are already some older questions regarding this topic, but in the meanwhile there are some new tools available.
I am especially interested in these tools:
Jammit
AssetHat
Rack PageSpeed
Jammit seems to can do everything that AssetHat can do and is also longer available. So where does AssetHat fit in?
Rack PageSpeed seems to do everything on the fly by directly working on the server response. Did you experience any performance issues by doing that? Would you recommend it over the other two solutions?
Hey there, I'm the author of AssetHat. Minification and concatenation are among the easiest performance boosts to implement; these features are common to Jammit, AssetHat, and rack-pagespeed. Rails has supported concatenation for a long time now (though it's done at runtime, rather than during deployment), and it's no surprise that Rails 3.1 supports both minification and concatenation during deployment.
The remaining features are what make each of these asset managers interesting. For example, Jammit is useful if you want to embed images and font files directly into your stylesheets. rack-pagespeed is also handy if you want to keep all your optimizations in a completely separate layer.
Inlining assets into CSS is great for static pages where stylesheets change infrequently. However, if your site is under active development, and the stylesheet changes even a tiny bit, the user's browser has to re-download the whole thing—including inline images and fonts that probably didn't change. It depends on the nature of your project.
If your assets are too big to inline or concatenate, AssetHat helps optimize for CDNs and parallel loading:
It takes great advantage of CDNs, whether it's Google's CDN, cdnjs (which uses Amazon's servers), or another CDN of your choosing. For example, just add <%= include_js :jquery %> to your layout (and a version number in a config file) to load jQuery from Google's CDN. If you're in dev mode and have a local copy of jQuery, that loads instead—easy offline dev.
AssetHat can rewrite stylesheets' image URLs to use your CDN instead. This reads from your config.action_controller.asset_host setting, and is done at deploy time. Your original CSS is left untouched.
If you have several JS files to load, it's sometimes faster to load them in parallel than to concatenate them (i.e., force them to load serially). You can switch on LABjs mode easily: <%= include_js 'big-file-1', ..., 'big-file-n', :loader => :lab_js %>. If you don't have a copy of LABjs locally, or if you're in production, LABjs loads from Amazon's servers via cdnjs.
By using CDNs like Google's or Amazon's, your users can load more assets in parallel (because there are more hostnames), enjoy greater speed, and sometimes, not even need to download assets at all (e.g., if they already loaded Google's copy of jQuery via someone else's website).
I've used AssetHat on Heroku by setting my deploy script to simply run rake asset_hat:minify (to minify and concatenate CSS/JS), commit those changes to my repository, then do the actual deployment.
In case you haven't seen these already, you might be interested in:
a longer walkthrough of AssetHat's features
the official website
the technical readme
the extensive docs
If you need help setting it up, or have any other questions, feel free to message me on GitHub (rondevera) or Twitter (#ronalddevera).
Jammit won't work out of the box on Heroku as far as I know. One option seems to be to use the Heroku Jammit plugin to manage your assets - https://github.com/chebyte/heroku-jammit.
Alternatively, Jammit can be configured to output to /tmp: http://geekninja.blogspot.com/2011/04/making-jammit-jam-with-heroku.html
Rails 3.1 will include Sprockets to handle asset packaging, I think that's worth considering.
I am currently using jammit on heroku, together with amazon s3, and it works like a charm :)
I can't say much about the others tools because I have not used them.
Which one did you pick, in the end?
Fernando.

Can Rails' javascript_include_tag ignore previously-loaded scripts?

I'm using this line:
= javascript_include_tag :all, :recursive => true, :cache => true
in the footer of a Rails app to do the following:
Load all the scripts under public/javascripts recursively
In production, lump them all into one file (the :cache part)
However, I want to load one of these scripts in the head, because some inline JS depends on it.
Is there an option for javascript_include_tag to exclude files that have already been loaded?
I know it doesn't do this by default, because right now I see a script referenced twice in the source HTML.
javascript_include_tag is a simple html helper and doesn't track weather or not something has already been included on the page, so no, there isn't an option, sucks.
In place of this, you can solve your problem in a few ways:
Use something like Jammit, which I use right now and is an absolute joy. It packages all your javascripts up in production into one file, allows you to compress the shit out of them, and does the same for CSS. You configure it using a .yml file in your config directory, making it portable and easy to recursively include scripts from directories while still controlling the order in which they are included on the page or appended to the package. An alternative (less awesome IMHO) to Jammit is Asset Packager.
Use javascript_include_tag in the head. Not really the end of the world. Optimize later.
Not really Rails specific, but use head.js. head.js is pretty new but allows you to load many scripts quickly, in parallel, while preserving the execution order and taking callbacks to fire once your scripts are loaded but before the dom is ready. It includes a bunch of other goodies like HTML5 friendliness in older browsers. This option is interesting because you keep your scripts separate, or at least in different packages for maximum parallel download speed. I'm not sure weather or not downloading one huge compressed package serially in the <head> or even right at the footer, or loading things in parallel using head.js will be faster, but it sure makes managing these things easier.
I've used both head.js and Jammit recently and I must say, for heavy Javascript apps, they make things wonderfully easy.
In config/application.rb you can set the meaning of :defaults in the javascript_include_tag :
# JavaScript files you want as :defaults (application.js is always included).
config.action_view.javascript_expansions[:defaults] = %w(rails, jquery)
You can then use the :defaults parameter to use the tag in application.erb.html, or wherever you like:
<%= javascript_include_tag :defaults %>
Once you've done this at the bottom of your view template, you can of course include single scripts before it.
Now, I realise that you wanted to use the :all parameter, and load recursively, but this solution does give you more control, which I think you are going to need here.

How can all.js be created manually?

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.

In Ruby on Rails how can I combine multiple Javascript files at runtime?

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.

Resources