My rails app is working but its slug size is huge (220mb).
I am storing all assets on cloudfront with config.assets.digest = true and config.action_controller.asset_host = "something.cloudfront.net"
heroku run bash
In the slug, there is 30 times application-onedigest.js in public/assets, and same thing for stylesheets and images, so now the slug size is 220 mb.
Maybe one of my gem is doing middleware things (Rails asset_host, cloudfront and heroku) or maybe heroku is trying to optimize things (https://devcenter.heroku.com/changelog-items/328), but i don't think so. I don't want to exceed the maximum heroku slug size that is 300 mb, and i feel that is not normal.
How to remove old rails assets on heroku ?
EDIT
I made little commits in a css file, push to heroku, and compared slug. In the deploy process, there is those lines:
Running: rake assets:precompile
INFO -- : Writing /tmp/build_ff4eb6d7-303e-444d-9c88-938ab504ea8a/public/assets/application-700c7e1849c55312a94a353e60312500.css
Asset precompilation completed (9.60s)
Cleaning assets
Running: rake assets:clean
INFO -- : Removed application-48375ba5495e14b36afab9d4b9d97033.css
This is what i want. But when i compare the old and the new slug, there is the new application-700....css, and an another new mysterious application-a9b33ae58934ad161038cb3ebcee146c.css
And this one is actually used is the heroku webapp (when i explore css resources from the browser, after clearing cache).
So i guess precompile is done twice somewhere?
Temporary solution : heroku fork the app, i am back to 40 mb but there is still the problem.
EDIT
It seems it works when i precompile locally, but i don't like it as it violates 12factors.
Some things you'll want to consider:
rake assets:clobber
Heroku's file system
CDN
rake assets:clobber is an inbuilt way to remove old asset files from your public/assets directory. By running this command, either locally or on Heroku, you'll be able to actively remove the precompiled asset files on your system, allowing you to repopulate the folder with new files
Secondly, you have to remember Heroku runs an ephemeral file system. This means that each time you push your application to Heroku, it will just overwrite any of the files you had before, meaning (importantly), that it's not going to store your last assets. Each time you push, it will precompile the assets for you - which should ensure minimal space taken up with them.
--
Finally, if you find that your assets are taking up too much space on your application server, you may consider using a content delivery network (CDN) to serve the assets you need. You can use the asset_sync gem to push your assets to your CDN of choice
Most people tend to use a CDN with storage system to serve their assets. We use S3 with Cloudfront currently, but are looking to move to Rackspace's file serve system!
You can use the Heroku repo plugin (https://github.com/heroku/heroku-repo) and the repo:purge command to clean all the build assets out of your slug.
Using asset_sync gem is not ideal as you can run into deploy timeouts pushing all the assets over to S3 plus you end up with assets in two places. Remember S3 is not a content delivery network, you're better off using a CloudFront distribution and have it cache the assets directly from your application. See https://devcenter.heroku.com/articles/using-amazon-cloudfront-cdn for more details.
This solve it for me, in production.rb :
config.assets.compile = false
Heroku is no longer generating useless assets. I don't know how to remove the old assets in the same heroku app, but i used "heroku fork" to create a brand new heroku app with the same config / database and without old assets.
heroku run rake assets:clobber
Related
I've started learning rails and I've already built two apps, one simple blog app and one store app. Now I ran into a term precompile assets when uploading to heroku, can someone explain it to me is that necessary when deploying an app to production, because i've uploaded my store app to heroku without any problems?
Assets is your css + JS. Precompile assets mean that they get joined into single .css and another single .js. file (to load it in one HTTP request). And special mechanism of minifying get applied to both these files (to make them smaller). Rails by default is setup in a way, that it uses average files in dev and compiled files in prod. You can easily change this in configs, but you shouldn't do this unless you really know what you do.
If you want you can compile this files locally running rake assets:precompile and then put it into git. I think that you can disable/enable precompile during heroku deploy in heroku config. But, in general, I would stick with the very defaults.
More info on asset pipeline: http://guides.rubyonrails.org/asset_pipeline.html
Rails has an assets pipeline which consists of Sprockets and the assets helpers.
The assets pipeline will concat and minify your CSS and javascript and takes care of setting the correct paths to images and other assets. This is known as compiling the assets.
In development this is done on the fly for each request which lets you immediately see changes.
In production this would be far to slow so instead the assets should be compiled once at deploy time. Heroku does this automatically for you in a post-commit hook.
Pre-compiling is when you run rake assets:precompile locally and then upload or push the result to a server. This is done if you are deploying to a server without the support for the assets pipeline. For example if the production server does not have a javascript runtime which is required to run uglifier.
It adds tons of noise to the git change history and manually doing anything is a common source of user error. So pretty much it sucks and you only do it if you have to.
I'm trying to make a Rails app server its assets at S3. I'm not using any gems because want to do it manually to better understand the process. My questions regarding serving the static assets are:
Which assets should I upload to my S3 bucket: from my_app/assets or from my_app/public/assets?
If the second option, it means I have to precompile them first, right? And then upload the whole folder my_app/public (or my_app/public/assets?) ?
Since right now I'm deploying the website at heroku and the max size of the repo at heroku is 300Mb and the size of my assets is much bigger, how and should I at all make the app somehow "understand" that its assets are located at S3 so that when I say "git push heroku master" it won't upload all them from its my_app/assets or my_app/public/ folder?
You will need to change the config.action_controller.asset_host option on the Rails Configuration. Take a look at http://guides.rubyonrails.org/configuring.html#rails-general-configuration
You will indeed need to precompile the assets and sync them to S3. Remember to use RAILS_ENV=production. A good place to look at and then replicate manually would be in the asset_sync gem.
So the question basically boild down to this:
How do you efficiently handle changing assets in a production rails environment without the need to restart the server?
The problem we're experiencing is, we have to restart the Thin server that runs the app in order for the updated javascript files to be served.
Some background:
Right now we're generating data from a couple of long running tasks into javascript files once an hour so we can use it in our Rails app.
To be clear, we update/overwrite existing files, not adding new ones.
After generation we run these commands in order to re-precompile all the assets.
bundle exec rake assets:precompile
bundle exec rake rails_group=assets assets:clean RAILS_ENV=production
Still after clearing the browser cache and reloading the page we're being served the old assets.
Have you guys made any similar experiences; what did you do to work around it?
PS. Happy holidays to you all!
So, what we ended up doing is basically letting rails also serve static assets by setting
config.serve_static_assets = true
in config/environments/production.rb
and just putting the frequently changing javascript data files into a directory structure under public/.
This works grate since it also separates assets and data into different locations.
According to the Rails guide:
6 How Caching Works Sprockets uses the default Rails cache store to
cache assets in development and production.
Rails is going to cache your assets unless you tell it to not cache them. The whole point of the asset pipeline is to serve assets as quickly as possible by encouraging browsers and servers and the rails servers themselves to cache the assets.
If your use case involves redoing assets very often, maybe the asset pipeline isn't for you.
I have the option to precompile my assets locally in development or on my production server. I deploy with git, so I'd prefer not to have to check in all these assets (especially if they're using cache-busting digests).
Is there any advantage to precompiling assets locally (other than lacking write-access on the production machine)?
Your site doesn't need to be down when you precompile assets. If you use capistrano or similar tools, you precompile the assets in the server, then (after this and more steps have been completed) restart the app. Meanwhile the app is being served from the old code (and assets).
On the other side, I disagree about the "cache-busting" comment. Git is smart enough to understand a diff between two differently named files if possible. So the result would be exactly the same whether the names changed or not. In which case I completely agree that it's nonsensical to load the repository with generated data, like compiled assets.
I've found that compiling assets locally is much faster and then your site is down for a shorter period.
Of course, that depends on your server setup etc...
I have 2 environments for my app on heroku: staging and production, and I'm using Rails 3.1 assets pipeline.
I have set a custom config.action_controller.asset_host property to make my assets fetched from cloudfront on http://assets.myapp-staging.com or http://assets.myapp.com
The issue is that on Heroku, assets are always precompiled with the production environment. Which means that all the urls present in my css or js files target http://assets.myapp.com even in staging.
Any idea?
Your best bet is to do one of two things:
1) Use the new user-env-config labs add-on which makes your environment variables available during the slug compilation phase.
To use this simply:
$ heroku labs:enable user-env-compile -a myapp
-----> Enabling user-env-compile for myapp... done
WARNING: This feature is experimental and may change or be removed without notice.
For more information on this see here:
http://devcenter.heroku.com/articles/labs-user-env-compile
or
2) Don't use those assets. With the Asset Sync gem you can run the compilation of the assets once the application has been spun up in it's evironment. This will then sync your assets to S3.
For more information on this, check out:
http://devcenter.heroku.com/articles/cdn-asset-host-rails31