The problem at the moment stems from the fact that the frontend assets are developed in this style:
.foo {
background: url(../img/bar.png); /* Sometimes ../images/ */
}
but Rails expects them to be like this:
.foo {
background: image-url("bar.png");
}
The reason is that Rails contains an "Asset Pipeline" and assets (images, css, js, fonts) go through a compilation stage when deploying for production use (and this is handled dynamically in development mode). So an asset named img/bar.png
will be converted in to a URL like http://host3.my-asset-host.com/assets/bar-892389032abcd8367928.png
.
This enables Apache/whatever to set a really long expiry time (1 year is common) on all image/*, text/css and text/javascript files because if the content changes then the hash on the end of the converted URL will be completely different.
As things stand we have the current options:
-
Develop things in the frontend framework as they are, but it breaks Rails :-(
-
Develop things in the frontend as they are, but then override each rule that is "broken" (from Rails point of view) with a Rails-style declaration
-
After bower-installing the assets in to Rails, "fix" each 'broken' declaration so that it works, causing this step to be repeated after each bower-install
These are the simple options. There are two other options.
We could combine all CSS files that are bowerised (forming a mega-package) and likewise for all JS and host them all on http://(staticwhich|cloudfront|cloudfiles)/v1.0.1/assets/mega.css
, including images, fonts, etc and the combined mega packages would only use absolute URLs to that paths within that asset host (no ../
).
Each application would then set a asset prefix for including CSS/JS from the asset host that includes the version number they are tested against. Each application is then also allowed one single HTTP request for each of application-IDENTIFIER/HASH.css and application-IDENTIFIER/HASH.js, but these should also be pushed to the asset host.
This means that all assets can use long expiries (as they have either a vX.Y.Z string or an IDENTIFIER/HASH in the URL), there are no relative paths to break things and things are much simpler for application developers.
In fact: if absolute URLs are used to the asset host instead of url(../*)
then this goes away anyway...?
Instead of using relative paths to assets within the CSS files, declare a SASS variable at the top for the asset folder in use, such as:
$imageFolder: "../img/" !default;
.foo {
background: url("#{$imageFolder}bar.png");
}
This would be set to /assets/
for Rails applications in the application.css.scss
before any other includes, taking in to account that all assets are available under /assets
, abusing the fact that Rails assets are compiled once with a -IDENTIFIER/HASH suffix and one without.
They lose the ability to have long cache expiry times as they no longer have a unique identifier in the URL.
Each developer could define a function like this within their SCSS files:
@function image-url($value){
@return url("../img/#{$value}");
}
However, the problem is that this overrides Rails functionality (which is run after sass compilation). So this would somehow need to be inserted for non-Rails projects in a way that doesn't break Rails…
Haven't yet had any ideas on how to achieve this...
http://blog.grayghostvisuals.com/compass/image-url/