Rails image url in poduction - css

When I put my website in production using git push heroku master the url in my CSS does not refer to the right image url.
Here is my situation in development environment :
app/assets/images/logo.png is present
app/views/layouts/application.html.erb : <%= stylesheet_link_tag "style" %>
app/assets/stylesheets/style.css : background: asset-url("logo.png");
Here is my situation in production (when I "View Page source") :
I don't know how to find logo.png ?
Link to my CSS : <link href="/assets/style-75a5c3912777c4b39ba92d1893ac7815.css" media="screen" rel="stylesheet" />
In my (compressed) CSS I can find : background:asset-url("logo.png");
For the others images called directly from app/views/* it's ok (<%= link_to image_tag("xxx.png") %>)
In config/environments/production.rb I have :
config.assets.precompile += ['style.css']
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
config.assets.digest = true
config.assets.compile = true
config.serve_static_assets = true
I'm following this great tutorial.

SCSS
The problem, from what I can see, is that you're not using any CSS preprocessors (SCSS / SASS), cancelling out the ability for the Rails helper asset-url.
I'd do this to start with:
#app/assets/stylesheets/style.css.scss
background: asset-url("logo.png");
Asset Pipeline
This will make sense if you look at how the asset pipeline works
Basically, the asset pipeline is a place to put all your css / image / javascript files, which your application can call, either statically or dynamically. Whilst in development, the asset_pipeline works very well to provide you with a central location for all your files -- all being called dynamically.
--
Production
The "problems" happen when most people want to use the asset pipeline in production. Production generally requires static assets, which means precompilation:
In the production environment Sprockets uses the fingerprinting scheme
outlined above. By default Rails assumes assets have been precompiled
and will be served as static assets by your web server.
Asset precompilation is when Rails will "compile" your CSS / Image / Javascript files into a series of "minified" versions - making them much more efficient to load
The problem with the precompilation process is actually loses all the "dynamic" aspects of the files, meaning if you want to include things like asset-url, you'll need to use a preprocessor to manage the dynamic aspects of these files.

I resolve my problem thanks to multiple answers found here and somewhere else (can't found where anymore sorry). Here is my solution to make things work without putting all my ressources into the public folder.
I deleted all ressources from public/images & stylesheets & javascript
I renamed my style.css to style.css.scss.erb
I replace every background: url("../images/xxx.png"); to background: url(<%=asset_path "xxx.png"%>); from my CSS
I executed this command before pushing into production : bundle exec rake assets:precompile RAILS_ENV=production
Thanks #RichPeck for your post which helps me to understand the process of assets pipelines

Related

Virtual path provided not used in ASP.NET bundles

I have the following bundle in my BundleConfig:
bundles.Add(new StyleBundle("~/Content/Basic/globalCss").Include("~/Content/Basic/global.css"));
I am using the following to render the CSS bundle:
#Styles.Render("~/Content/Basic/globalCss")
On my local machine (debug environment) the CSS file is included/loaded via its absolute path. I have compilation turned off/false for debug, so this makes sense. When I push to a QA environment (compilation turned on/true), I see the following virtual path being included in the page:
<link href="/Content/globalbasicCss?v=6i8x1Cxf8pXm5g9uxAk8-wcO02DFmeAgYLWpJk-3r_g1" rel="stylesheet">
This was the old virtual path that I had was ~/Content/globalbasicCss.
Why is my bundle not using the new virtual path I provided ~/Content/Basic/globalCss? Is this because there were no changes made to the CSS file included in the bundle, by any chance?
That is the bundling and minification feature. Your CSS bundle is minified and if you had more files they would be bundled in one file.
This happens when you usually build in release mode with the web.config setting
<compilation debug="false">
More information here - http://www.asp.net/mvc/overview/performance/bundling-and-minification
Turns out I needed to make changes to the actual bundled CSS files in order for that bundle virtual path to update. I'm not sure why this is, and would appreciate anyone with better understanding of ASP.NET bundling explaining why this happens this way.

CSS/JS bundle in single file in mvc when publish with release option

I have created MVC application. When I publish the application on Azure with release option, all css and js file load in a single bundle in page. (Open view source of page then displays a single link for css).
When I publish a site with Debug option in publish profile then all CSS load individual.
My problem is when publish site with release option theme not load correctly, but with debug option theme loads correctly. I want to publish my application with Release option only. If anyone face this issue before and get any solution then please help me.
I have experienced this before when using bundling.
Say for instance your css file is located at: /Content/css/css.css
This css file then makes a reference to another file, or for example an image at /Content/images/image1.png via url('../images/image1.png').
You then set up your css bundle # /bundles/css.
All appears great in debug mode. However, when you set <compilation debug="false" .... in your web.config, suddenly the references made in the css file breaks. If you open your console in Firebug/Chrome dev tools and check the network tabs, you'll see resources failing to load, from an incorrect URL.
This happens because when debug mode is off, all the files are bundled and minified like they would be in production. In this case, the CSS file would be bundled and served from the URL /bundles/css. This results in the relative URL reference breaking. Where it once referenced /Content/images/image1.png, it now references /images/image1.png.
You have a few options to solve this:
Serve your bundled css files from the same folder as the actual css files. eg. /Content/css/cssbundle. This can become very tedious quickly.
Change all relative references in your css files to absolute references. eg. ../images/image1.png would become /Content/images/image1.png. This does mean you can't use a lot third party CSS bundled out of the box, you would have to check/change relative references if you wanted to bundle them.
Use the BundleTransformer nuget package. It automatically transforms relative urls to absolute ones during the bundling process.
The main differences of StyleTransformer and ScriptTransformer classes from a standard implementations: ability to exclude unnecessary assets when adding assets from a directory, does not produce the re-minification of pre-minified assets, support automatic transformation of relative paths to absolute in CSS-code (by using UrlRewritingCssPostProcessor), etc.
I personally recommend 3 as it is the easiest to maintain long term.

The changes not updating on server

I have build MVC 5 application which works fine when running via VS. When I publish it to the server first time it also works. Now I have made few correction to my css file and publish whole project again but website still see the old css file. I have removed all files from the server and tried few more times but it is still the same. When I check the css file on the server, the changes are inside the file.
I think it is related to MVC bundling as when I check the source it says that is accessing different file which is not even located on the server:
<link href="/Content/cssmain?v=Ikj7NnMg3q9kTHR7ynWOJDQFGMZl3mtVMi_2EkOJxc41" rel="stylesheet"/>
How can I force VS to minificate my css file again?
I've tried cleaning, rebuilding but no luck
Edit:
My bundle set up look like below and all files are located on the server in Content folder.
bundles.Add(new StyleBundle("~/Content/cssmain").Include(
"~/Content/bootstrap.css",
"~/Content/site.css",
"~/Content/ilightbox.css",
"~/Content/bannerscollection_zoominout.css"));
Many thanks
I think it is related to MVC bundling as when I check the source it says that is accessing different file which is not even located on the server:
CDN location? External Css lib (yours or 3rd party)? unsure what you meant by "not located on server"?
Yup, it does (look like ASP.net Bundling in action) - check your Global.asax, App_Start/BundleConfig or _AppStart and see if the bundle configuration setup point to/reference the "correct" locations for your css (and or script).
Is it just you experiencing getting the old css file loaded? Or anyone who views the site?

Rails 4; asset helper not pointing to fingerprinted image asset (failure to load in production # Heroku)

This problem is driving me crazy... I think I've tried every conceivable combination of Sass file, ERB file, asset helper, image helper, etc. etc. Someone please give me new ideas!
Context:
Rails apps require use of asset helpers so that when the assets are precompiled, the source will be a fingerprinted asset file. I.e., if you just called img src="X.jpg", the site in production would look for X.jpg, but the file in public/assets has actually been fingerprinted as X-as;diofua;wemfiwaejfoiawefo.jpg. The only way to get to that fingerprinted file is to use an asset helper, e.g., image_url ('X.jpg').
Right now in my live site, I'm using an asset helper, but for whatever reason, it's not pointing at the fingerprinted asset. Note that the assets are found in development (but again, that's because there's no fingerprint added in development).
Code
Image titled "classic-map.png", located in app/assets/images/galleria
Image is called from a css.erb file required in the application.css file. In the css.erb file, I have the following code:
background-image: url(<%= asset_path 'galleria/classic-map.png' %>);
For reference, http://guides.rubyonrails.org/asset_pipeline.html
Note that I'm choosing to write this as a css.erb file, hence the use of asset_path vs. asset-path. Also, I initially thought that the issue might have been in interpolation, but in the page source, the url is definitely working, it's just that it's pointing at url(galleria/classic-map.png) instead of url(galleria/classic-map-apsoidufalskjf;kasj.png)
A million kudos to whoever can help!
For what it's worth, this happened to be AGAIN, and this time I could not use the hack because I desperately needed the fingerprint. So somehow, magically, I ran a rake assets:clobber and heroku run rake assets:clobber to clean all assets, and then a straight up git push to force Heroku to do the precompilation for me. That did it, and everything works.
Now, when this happens, I clobber assets locally & in production and push, forcing Heroku to precompile remotely. Similar to #user2880239's answer. I have stopped precompiling locally and checking into git.
I sat with a Sr Rails developer who still couldn't help me fix this. But the workaround we ended up using was that we just manually removed the asset fingerprint in the public folder (since the fingerpoint is what the asset helper is meant to point to).
I.e., the file galleria/classic-map-587854758918434124.png we just manually changed back to galleria/classic-map.png and it works fine.
Note that if you do this 'hack', the next time you precompile assets, Rails will create another fingerprinted asset, so you'll have duplication unless you want to keep deleting the additional fingerprinted asset each time. For me, I don't care about the duplication, I care about not thinking about this anymore.
Did you check RAILS_ENV ?
bundle exec rake assets:precompile RAILS_ENV=production
I had the same problem you did. This blog post helped me.
What I did was change a few things in my config/environments/production.rb file, namely...
config.serve_static_assets = true
config.action_dispatch.x_sendfile_header = ‘X-Accel-Redirect’
config.assets.compile = true
Note that you might not need to 'add' any of those properties since they may be pre-set to false or merely commented out.
Then I did the heroku dance:
rake assets:precompile
git add .
git commit -m "Fix static assets"
git push
git push heroku
I'm having the same issue. I even tried the helper from the rails console from heroku, and the helper works fine there!!
$ heroku run rails console
Running `rails console` attached to terminal... up, run.8071
Loading production environment (Rails 4.1.7)
irb(main):001:0> puts helper.image_path("bg.jpg")
/assets/bg-00acfb7dbe138102509d82ac2313c24d.jpg
My final "solution" was to update config.assets.compile = true in config/environments/production.rb to fallback to the non fingerprinted image.
Hope this solution could help to someone. And if you had any real solution, please make me know!
The answer to this for Heroku is in their Pipeline docs here.
By doing clobber you are basically cache-busting all your assets and forcing all clients to reload all static assets (even if they have not changed) every time you deploy your code. That is not advisable as it means every time you deploy ALL clients will experience slow loading times until all assets get cached again.
Your css file has a dependency to your image file, so you need to tell the assets pipeline about this by putting this at the top of your css:
//= depend_on_asset "galleria/classic-map.png"
This tells sprockets that if class-map.png gets a new fingerprint then the css must also get a new fingerprint. So it will only recompile the files (and dependencies that changed).
Also for others landing here, be aware that if you are using asset_path from ANYWHERE other than a view (eg in a model) you need to prepend the full context:
ActionController::Base.helpers.asset_path('your-image.png')
More info here.

rails caching problem with css

I have two different css files... style.css and style_main.css
both are used separately in different layouts for the same application. In development mode everything works fine, but when in production mode, caching happens and both css files are loaded as all.css?xxxxxxx but unfortunately all.css is made from style.css and does not update with the change in layout. how do i prevent this???
When you deploy the code to the production server, you are probably also deploying the all.css file. Have you tried excluding this file from your version control system? When you update style.css etc on your development machine, commit the changes and then redeploy, rails will re-generate all.css if it finds that it isn't already in the public folder.

Resources