I am trying to figure out how to get boostrap-sass working in production mode. I am using apache to reverse proxy to either webrick or puma, but serve the static assets in public/assets directly. When I precompile assets, the bootstrap css gets included into the application-(hash).css and it works correctly.
However the compiled css references an image file (glyphicons-halfling.png) without appending the hash of the file contents. The image file is included in public/assets directory, and it is possible to browse to it by putting the correct filename in the address bar, but the filename in the css does not match it. I have created a simple demo app that demonstrates this problem, code is on my github page
The glyphicon filename is glyphicons-halflings-c806376f05e4ccabe2c5315a8e95667c.png
[EDIT]
Would still like an answer to this question, but i've just renamed the offending files to remove the hash. Since these files are unlikely to change frequently then this should work fine
Think I have it cracked, when you run rake assets:precompile, it seems that you must prefix it with RAILS_ENV=production in order for it to work properly in production mode (I guess that kind of makes sense). If you don't, some of your assets will get precompiled, but the helper methods will not generate the correct paths.
tl:dr, RAILS_ENV=production rake assets:precompile
Related
Before deploying a new version of my app on Heroku, I need to do this in my console (for css and js to work on Heroku): RAILS_ENV=production bundle exec rake assets:precompile.
I just picket this code line from a forum, and I my questions is:
1) Why do I need to do this?
2) Is it possible to implement something more permanent in my Rails code so it does this precompiling automatically (so I don't need to write it manually every time I do some changes in my css or js files)?
1) Why do I need to do this?
There are lot of js files and css file in rails app generally. The above command compress and minified all those files which will reduce the number of requests that browser makes to render a web page. Web browsers are limited in the number of requests that they can make in parallel, so fewer requests can mean faster loading for your application.
More
2) Is it possible to implement something more permanent in my Rails code so it does this precompiling automatically (so I don't need to write it manually every time I do some changes in my css or js files)?
Yes. Heroku automatically compiles your assets if you dont include public/assets/manifest.yml for rails 3 and in rails 4 it is public/assets/manifest-<md5 hash>.json
More
Related Answer : Automatically precompile assets before pushing to Heroku
In your production.rb
config.assets.compile = true
I'm developping a Rails4 application with heroku hosting, and i encounter a bit of a problem:
I have a helper method to randomly pick an image by its path in /assets/images/path_to_image and this helper method is called in my HAML file. It works perfectly in my local environment. The images urls are stored in the DB. The problem is that Heroku changes the image names from logo.jpg to logo-a6d14b20c77aa6466e616313edcd3d34.jpg which makes my helper method useless. Any idea on how i could solve this problem? Is it a matter of pre-compiling the assets ?
Thanks a lot
B.
In rails4 by default assets gets the digest URL with them and getting served.
If you want you can use some middleware to redirect assets from non digest path to digest path.
or you can turn off the digest in production.rb file all together like below.
config.assets.digest = false
If you want that redirect solution I can post here as well.
Let me know!
Is it a matter of pre-compiling the assets?
Yes, I would say so
The problem you've got is that production environments compile all your assets, and consequently give you the hashed file-name you're seeing. The reason why this is a problem is that if you're referencing a static file (logo.png) in CSS or HTML, the compiled path will be different, causing the problem to occur. We learnt if you're going to reference any assets, always use a dynamic file (.scss / .haml / .html.erb) and then use the provided helpers
The way around this is to use the asset path helpers, which are basically like this:
image_path
asset_path
Heroku
It seems you're well versed with Rails so I don't bore you with the details
Heroku works best by serving static assets & pre-compiling them before you deploy:
#config/production.rb
config.serve_static_assets = true
You then need to pre-compile the assets with the production environment, like this:
> rake assets:precompile RAILS_ENV=production
This goes through your assets & assigns all the correct paths, if you've used the asset path helpers as mentioned above. After that, push to heroku & I always pre-compile the assets when on Heroku too (we use the asset_sync gem):
> heroku run rake assets:precompile --app [app_name]
I have compiled assets using following command in rails 3.2 for production purpose.
RAILS_ENV=production bundle exec rake assets:precompile
After running above command an assets a folder is created under public. Now I want to removed non-compile assets folder because it is huge. But I have need answers to following questions.
Do I need the assets folder that contains non-compiled assets ?
If yes then what is purpose of having a non-compiled assets folder ?
I will appreciate your help.
Yes, keep them.
The purpose is that when they are taken from assets to public they are usually minified and combined, greatly saving space and helping to reduce download time for end users when using the site. But when you need to make changes, use the originals in assets.
In development mode (local, on your box), the assets version is used and is useful in traces while developing/debugging as they point to the actual source code lines in question and have the original (usually longer and meaningful) variable names.
Most likely you will need to make changes to one of your assets in app/assets in the future.
app/assets has the original source files with original formatting and these are the files you should change.
Theoretically you could delete the source files in app/assets, but then you won't be able to change anything and re-compile with those changes.
Everything works great in Development. And app deploys as normal with Capistrano. Assets (javascript & css) appear to be fully pre-compiled and each, along with images, are given a "fingerprint". Problem is when using image_tag("image-name.png") in my view the html it creates in production doesn't include the 'fingerprint'.
The rendered HTML we get in production:
<img alt="Image-name" src="/assets/image-name.png" />
instead of, what I would expect, should be:
<img alt="Image-name" src="/assets/image-name-b89cae2830c2901f844c353b3f3942fe.png" />
So which of Rails 3.1's myriad config options did we botch?
Edit
The troublesome images appear to be those included in a 3rd-party Colorbox image viewing tool we use. Rails 3.1 is fingerprinting its assets (border.png, etc.) but, clearly, the source code for this javascript library doesn't use helpers like image_tag. So in production it is still looking for images named /assets/colorbox/border.png. Currently images are in /vendor/assets/images and work fine in Development. Is there a way to prevent just these images from being "fingerprinted"?
Well, here's how I hacked the 3rd-party files to make things work:
The offending images were in files like vendor/assets/stylesheets/colorbox.css. I first changed the extension of the files to .scss then I changed each url(colorbox/image.png) to image_url("color box/image.png") and now everything is peachy. Assets are served normally in development and fingerprinted in production.
Still like to see the "proper" way to add 3rd-party (vendor) javascript libraries & css to a Rails 3.1 app. Rails team must have anticipate a drop-in solution that doesn't require editing?!? So, please, feel free to offer up other solutions.
Aside: where I previously had manually configured my Capistrano recipe with:
run "cd #{release_path}; RAILS_ENV=production bundle exec rake assets:precompile"
…and its accompanying after deploy:update_code …. I have now removed those lines and instead added load 'deploy/assets to my Capfile. I don't think this makes any difference in the above problem but I wanted to document it anyway as adding your own recipe for pipeline precompiling is no longer necessary in Capistrano 2.8 as it was in the 3.1rc days.
I have put all my images for my admin theme in the assets folder within a folder called admin. Then I link to it like normal ie.
# Ruby
image_tag "admin/file.jpg" .....
#CSS
.logo{ background:url('/assets/images/admin/logo.png');
FYI. Just for testing I am not using the asset_path tag just yet as I have not compiled my assets.
Ok all good so far until I decided to update an image. I replaced some colors but on reload the new styled image is not showing. If I view the image directly in the browser its still showing the old image. Going one step further I destroyed the admin images folder. But it has broken nothing all the images are still being displayed. And yes I have cleared my cache and have tried on multiple browsers.
Is there some sort of image caching going on? This is just local development using pow to serve the pages.
Even destroying the whole images folder the images are still being served.
Am I missing something?
In 3.1 you just get rid of the 'images' part of the path. So an image that lives in /assets/images/example.png will actually be accessible in a get request at this url - /assets/example.png
Because the assets/images folder gets generated along with a new 3.1 app, this is the convention that they probably want you to follow. I think that's where image_tag will look for it, but I haven't tested that yet.
Also, during the RailsConf keynote, I remember D2h saying the the public folder should not have much in it anymore, mostly just error pages and a favicon.
You'll want to change the extension of your css file from .css.scss to .css.scss.erb and do:
background-image:url(<%=asset_path "admin/logo.png"%>);
You may need to do a "hard refresh" to see changes. CMD+SHIFT+R on OSX browsers.
In production, make sure
rm -rf public/assets
bundle exec rake assets:precompile RAILS_ENV=production
happens upon deployment.
For what it's worth, when I did this I found that no folder should be include in the path in the css file. For instance if I have app/assets/images/example.png, and I put this in my css file...
div.example { background: url('example.png'); }
... then somehow it magically works. I figured this out by running the rake assets:precompile task, which just sucks everything out of all your load paths and dumps it in a junk drawer folder: public/assets. That's ironic, IMO...
In any case this means you don't need to put any folder paths, everything in your assets folders will all end up living in one huge directory. How this system resolves file name conflicts is unclear, you may need to be careful about that.
Kind of frustrating there aren't better docs out there for this big of a change.
In rails 4 you can now use a css and sass helper image-url:
div.logo {background-image: image-url("logo.png");}
If your background images aren't showing up consider looking at how you're referencing them in your stylesheets.
when referencing images in CSS or in an IMG tag, use image-name.jpg
while the image is really located under ./assets/images/image-name.jpg
http://railscasts.com/episodes/279-understanding-the-asset-pipeline
This railscast (Rails Tutorial video on asset pipeline) helps a lot to explain the paths in assets pipeline as well. I found it pretty useful, and actually watched it a few times.
The solution I chose is #Lee McAlilly's above, but this railscast helped me to understand why it works. Hope it helps!
The asset pipeline in rails offers a method for this exact thing.
You simply add image_path('image filename') to your css or scss file and rails takes care of everything. For example:
.logo{ background:url(image_path('admin/logo.png'));
(note that it works just like in a .erb view, and you don't use "/assets" or "/assets/images" in the path)
Rails also offers other helper methods, and there's another answer here: How do I use reference images in Sass when using Rails 3.1?