Should I use Sprockets in Rails? - ruby-on-rails

When I'm testing my app on a vps through sublime and sftp, these Sprockets cache files always take forever (figuratively) to sync. What are the consequences of disabling Asset Pipeline? Will my app perform noticeably poorly?

What are the consequences of disabling Asset Pipeline? Will my app perform noticeably poorly?
Yeah, the asset pipeline is there for a reason, quoting the guide:
The asset pipeline provides a framework to concatenate and minify or compress JavaScript and CSS assets. It also adds the ability to write these assets in other languages and pre-processors such as CoffeeScript, Sass and ERB.
The concatenation of assets leads to fewer HTTP requests (connection setups) which is, at least for HTTP 1.1 considered as a best practice. Minification speaks for itself I guess. Take a look at the guide to get a full grasp of the consequences.
I'm not sure what exactly you mean with sprocket cache files and which environment (as in Rails.env) you're using on your VPS.
You can also compile the assets on the VPS, which might be quicker than uploading. (See compile/precompile section in the guide).
For testing purposes you could also run in the development environment, where the assets will be compiled on demand.

Related

Rake Pipeline or Rails Asset Pipeline

Trying to understand a few things about rails:
I have used rake-pipeline with rake-pipeline-web-filters successfully in the past for my front-end projects.
Recently, with a rails backend, My front-end assets are getting produced using the Rails Asset pipeline. I take it they are both similar but I am failing to align it in my head how it maps to the Assetfile way of doing things in rake pipeline.
So, questions:
Is Rake Pipeline an alternative to Rails Asset pipeline? If yes, why and what is the history & pros/cons of these two solutions? If not, how are they related?
With Rake pipeline, you addon the excellent rake-pipeline-web-filters to get all the concatenation, minification, pre-processing like scss, minispade etc. With Asset Pipeline, it seems hard to configure. One immediate limitation is that all my JS is eval'd immediately and I dont have support for minispade in the Assset Pipeline. The alternative to that is the minispade-rails gem.
In general, I am trying to understand how to go about getting a similar build process with rake pipeline Assetfile in Rails Asset pipeline.
Can someone clarify these two build processes and how to generally think about them?
Is Rake Pipeline an alternative to Rails Asset pipeline? If yes, why and what is the history & pros/cons of these two solutions? If not, how are they related?
rake-pipeline is not a direct alternative to sprockets. rake-pipeline is infinitely more flexible and more powerful. The asset pipeline is really just a preprocessor with concatenation. It does not make things like source maps and module wrapping easy. Sprockets does "dependency management". I quote dependency management because writing something =require inside a javascript file is a horrible way to "manage dependencies".
Rake pipeline defines a the steps required to build assets. This is the pipeline. Here's a build process you may think of:
Compile coffeescript into javascript
Wrap all javascript files in minispade modules
Concatenate all the files
Minify the concatenated file.
You can construct very complicated build pipeline. See Iridium's Assetfile for probably the most complex rake pipeline example in the world. Rake-pipeline is not just for constructing assets for web applications. It can be used to build any sort of code base. Ember.js uses it to construct release files for both Ember.js and Ember-Data. You could do this with sprockets, but it would be a huge waste of time and extremely awkward.
Sprockets seems to be optimized for development, where rake-pipeline is optimized for complex applications. Individual assets are available in development. This makes developing faster because assets don't have to be concatenated (only preprocessed if need be). This is not possible with rake-pipeline. Rake-pipeline only cares about inputs and outputs. The intermediate build files are not accessible.
You can use rake-pipeline inside of rails if you like. The rake-pipeline gem bundles a rails engine to replace the asset pipeline with itself. If you are building a complex frontend application I may recommend this. If you only want to wrap JS files in modules, then you can look into the various projects for the asset pipeline.
With Rake pipeline, you addon the excellent rake-pipeline-web-filters to get all the concatenation, minification, pre-processing like scss, minispade etc. With Asset Pipeline, it seems hard to configure. One immediate limitation is that all my JS is eval'd immediately and I dont have support for minispade in the Assset Pipeline. The alternative to that is the minispade-rails gem.
See previous paragraph.
In general, I am trying to understand how to go about getting a similar build process with rake pipeline Assetfile in Rails Asset pipeline.
This is impossible with sprockets. Sprockets functionality is really a subset of rake-pipeline. Rake pipeline can do everything sprockets can do and do it better. The downside is that it requires more configuration.
I recommend you take a look at assetfile I linked. It can give you an idea what you can do with rake-pipeline. Here are some thing's I've done with rake-pipeline.
Include environment specific JS/CCS (like production, development, test) etc in my final build
Allow other code to tie into my build process with hooks
Create initializer files for my Ember application
Precompile handlebars templates
Strip out assertions not required in production code.
Generate an HTML5 Cache manifest from my inputs
You could do all of these with the asset pipeline but it's not worth the effort.

When to use the asset pipeline

I'm serving a semi-static site with rails, just to get used to rails conventions.
Do I really need to use the asset pipeline to serve the .css and .js?
I could always precompile my .scss and coffee-script before their on the server.
and by semi-static, I mean that I may include some gems to do syntax highlighting or some other little tasks.
I guess it would be good practice?
I'm super new to rails and programming in general, by the way.
I just want another opinion.
Thanks, in advance.
You should use the asset pipeline if you are using rails 3.1 or above. It is far faster than the previous serving of assets in rails -- among other things, it munges and minifies the files.
You should always precompile your assets in production, whether or not you are using straight .css or .scss because if you don't precompile your assets, rails will still have to compile them at runtime.

config.assets.compile=true in Rails production, why not?

The default Rails app installed by rails new has config.assets.compile = false in production.
And the ordinary way to do things is to run rake assets:precompile before deploying your app, to make sure all asset pipeline assets are compiled.
So what happens if I set config.assets.compile = true in production?
I wont' need to run precompile anymore. What I believe will happen is the first time an asset is requested, it will be compiled. This will be a performance hit that first time (and it means you generally need a js runtime in production to do it). But other than these downsides, after the asset was lazily compiled, I think all subsequent access to that asset will have no performance hit, the app's performance will be exactly the same as with precompiled assets after this initial first-hit lazy compilation. is this true?
Is there anything I'm missing? Any other reasons not to set config.assets.compile = true in production? If I've got a JS runtime in production, and am willing to take the tradeoff of degraded performance for the first access of an asset, in return for not having to run precompile, does this make sense?
I wrote that bit of the guide.
You definitely do not want to live compile in production.
When you have compile on, this is what happens:
Every request for a file in /assets is passed to Sprockets. On the first request for each and every asset it is compiled and cached in whatever Rails is using for cache (usually the filesystem).
On subsequent requests Sprockets receives the request and has to look up the fingerprinted filename, check that the file (image) or files(css and js) that make up the asset were not modified, and then if there is a cached version serve that.
That is everything in the assets folder and in any vendor/assets folders used by plugins.
That is a lot of overhead as, to be honest, the code is not optimized for speed.
This will have an impact on how fast asset go over the wire to the client, and will negatively impact the page load times of your site.
Compare with the default:
When assets are precompiled and compile is off, assets are compiled and fingerprinted to the public/assets. Sprockets returns a mapping table of the plain to fingerprinted filenames to Rails, and Rails writes this to the filesystem. The manifest file (YML in Rails 3 or JSON with a randomised name in Rails 4) is loaded into Memory by Rails at startup and cached for use by the asset helper methods.
This makes the generation of pages with the correct fingerprinted assets very fast, and the serving of the files themselves are web-server-from-the-filesystem fast. Both dramatically faster than live compiling.
To get the maximum advantage of the pipeline and fingerprinting, you need to set far-future headers on your web server, and enable gzip compression for js and css files. Sprockets writes gzipped versions of assets which you can set your server to use, removing the need for it to do so for each request.
This get assets out to the client as fast as possible, and in the smallest size possible, speeding up client-side display of the pages, and reducing (with far-future header) requests.
So if you are live compiling it is:
Very slow
Lacks compression
Will impact render time of pages
Versus
As fast as possible
Compressed
Remove compression overheard from server (optionally).
Minimize render time of pages.
Edit: (Answer to follow up comment)
The pipeline could be changed to precompile on the first request but there are some major roadblocks to doing so. The first is that there has to be a lookup table for fingerprinted names or the helper methods are too slow. Under a compile-on-demand senario there would need to be some way to append to the lookup table as each new asset is compiled or requested.
Also, someone would have to pay the price of slow asset delivery for an unknown period of time until all the assets are compiled and in place.
The default, where the price of compiling everything is paid off-line at one time, does not impact public visitors and ensures that everything works before things go live.
The deal-breaker is that it adds a lot of complexity to production systems.
[Edit, June 2015] If you are reading this because you are looking for a solution for slow compile times during a deploy, then you could consider precompiling the assets locally. Information on this is in the asset pipeline guide. This allows you to precompile locally only when there is a change, commit that, and then have a fast deploy with no precompile stage.
To have less overhead with Pre-compiling thing.
Precompile everything initially with these settings in production.rb
# Precompile *all* assets, except those that start with underscore
config.assets.precompile << /(^[^_\/]|\/[^_])[^\/]*$/
you can then simply use images and stylesheets as as "/assets/stylesheet.css" in *.html.erb
or "/assets/web.png"
For anyone using Heroku:
If you deploy to Herkou, it will do the precompile for you automatically during the deploy if compiled assets are not included (i.e. public/assets not committed) so no need for config.assets.compile = true, or to commit the precompiled assets.
Heroku's docs are here. A CDN is recommended to remove the load on the dyno resource.
It won't be the same as precompiling, even after that first hit: because the files aren't written to the filesystem they can't be served directly by the web server. Some ruby code will always be involved, even if it just reads a cache entry.
Set config.asset.compile = false
Add to your Gemfile
group :assets do
gem 'turbo-sprockets-rails3'
end
Install the bundle
Run rake assets:precompile
Then Start your server
From the official guide:
On the first request the assets are compiled and cached as outlined in development above, and the manifest names used in the helpers are altered to include the MD5 hash.
Sprockets also sets the Cache-Control HTTP header to max-age=31536000. This signals all caches between your server and the client browser that this content (the file served) can be cached for 1 year. The effect of this is to reduce the number of requests for this asset from your server; the asset has a good chance of being in the local browser cache or some intermediate cache.
This mode uses more memory, performs poorer than the default and is not recommended.
Also, precompile step is not trouble at all if you use Capistrano for your deploys. It takes care of it for you. You just run
cap deploy
or (depending on your setup)
cap production deploy
and you're all set. If you still don't use it, I highly recommend checking it out.
Because it is opening a directory traversal vulnerability - https://blog.heroku.com/rails-asset-pipeline-vulnerability

Should I port my existing Jammit asset pipeline to the new Rails 3.1 version?

We've implemented Jammit for asset caching, compression and optimization in our Rails application. It's fully integrated with our continuous integration process and works well. That said, I am seeing 3.1 introduces a new canonical asset pipeline based on Sprockets.
Are there advantages to the Sprocket based approach that would merit porting our system? I do not want to spend time converting our system if there are no benefits.
I have already used Sprocket and Jammit and the main advantage of the Rails 3.1 approach is the complete and native integration of Sprocket, not the gem itself. I'm not a specialist but both gems are great and, for me, equivalent.
The rails 3.1 assets pipeline provide a clean architecture for js and css files and the native use of associated gems (sass, coffee-script, sprocket). If in your app you already have a clean tree for your files and a great integration of your gems, don't change anything !

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.

Resources