Great module Mike!
I note that the advagg module has a function advagg_css_js_file_builder()
This advagg function (advagg_css_js_file_builder) is partly based on the D6 core use of the functions; drupal_build_js_cache() and drupal_build_css_cache()
I have some 'picky' issues with the 'cutting' of options with the advagg version of this (see below):
The D6 Core version () has this nice option:
function drupal_build_css_cache($types, $filename) {
....
....
if (!file_exists($csspath .'/'. $filename)) {
// Build aggregate CSS file.
foreach ($types as $type => $css) {
// Only 'module' or 'theme' stylesheets can be aggregated.
if ($type == 'module' || $type == 'theme') {
foreach ($css as $stylesheet => $cache) {
if ($cache) {
$contents = drupal_load_stylesheet($stylesheet, TRUE);
// Return the path to where this CSS file originated from.
$base = base_path() . dirname($stylesheet) . '/';
_drupal_build_css_path(NULL, $base);
// Prefix all paths within this CSS file, ignoring external and absolute paths.
$data .= preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $contents);
}
}
}
}
.....
.....
}
So with the original D6 Core code for drupal_build_css_cache() we have a standard practice of manipulating / changing the drupal_build_css_path, base_url and base_path.
Why is this of value?
OK, both the CDN module and ADVAGG do NOT (currently) rewrite any of the image paths in CSS files (eg: background:url(../image.....))
This is a problem for me if; 1) I intend to use or alter the $base_url or $base_path, or 2) Utilize a CDN that has high overheads on mapping a CNAME domain name to refer to the relative CSS image urls.
My thoughts / answer / and tested code change (to advagg.module) is below:
if ($type == 'css') {
$data = advagg_build_css_bundle($files);
+ $baseURI = variable_get('my_cdn_css_base_url', '');
+ $data = preg_replace('/url\(\s*[\'"]?\/?(.+?)[\'"]?\s*\)/i', 'url('.$baseURI.'/$1)', $data); }
elseif ($type == 'js') {
$data = advagg_build_js_bundle($files);
}
// Invoke hook_advagg_js_alter() or hook_advagg_css_alter to give
// installed modules a chance to modify the data in the bundle if
// necessary.
The collection of the required variable_get('my_cdn_css_base_url', '') results from a simple D6 settings.php like this;
if (file_exists('sites/all/modules/cdn/cdn.module')) { // if Drupal Module CDN exists
$my_cdn_css_url = 'http://small.gdlcdn.com/802C5F/cdn1'; // get base url to add to CSS images
$my_cdn_mapping = $my_cdn_css_url . '|.css'."\n";
$my_cdn_mapping .= 'http://small.gdlcdn.com/802C5F/cdn2|.js'."\n";
$my_cdn_mapping .= 'http://small.gdlcdn.com/802C5F/cdn3|.jpg .png .gif .ico'."\n";
$my_cdn_mapping .= 'http://small.gdlcdn.com/802C5F/cdn4|.pdf'."\n";
$conf['cdn_basic_mapping'] = $my_cdn_mapping;
$conf['my_cdn_css_base_url'] = $my_cdn_css_url;
}
Note how I have achieved to re-map the CSS image urls to an absolute path = 'http://small.gdlcdn.com/802C5F/cdn1'
Prior to this change, I had some 'suffering' wondering what had changed in comparing (the original) D6 Core use of advagg's clone 'advagg_css_js_file_builder()'
Notes: I use the Edgecast CDN for all my website static asset needs. I prefer NOT to use the Edgecast 'CNAMES' DNS option = lookup overheads!
Thanks for makinh a great static asset tool!
Comments
Comment #1
Peter Bowey commentedNotes: When I have more *time*, I intend to replace the 'above' use of
with:
The older method of 'preg_replace' at the top of this was used to prove the function / idea - not perfect it.
Comment #2
mikeytown2 commentedDid you look at the advagg_build_css_bundle function? It looks VERY similar to drupal_build_css_cache(); it should behave the same. Changing the $base_path should work with advagg & core; changing $base_url doesn't appear to change the CSS output in core, thus it won't work in advagg. Did you end up hacking core to make this work for your use case?
What your asking for is something like an advagg_css_cdn module (not built yet). Rewrite the CSS file contents to point to the CDN instead of the server, correct? The thing is if the CSS file is served from the CDN then all the images referenced by the CSS file will be loaded from that CDN as well; as long as they are not an absolute reference. I realize that this may not be ideal for everyone so I am open to creating an advagg_css_cdn module.
If you wish to have this now without hacking at advagg, you can use hook_advagg_css_alter to alter the $data variable before it is written to disk. In either case, we need to be aware of module weights and have this adjust to run after the CSS Embedded Images module. If your wondering the proposed advagg_css_cdn module would use this hook as well.
Comment #3
Peter Bowey commentedThanks Mike,
Simply stated, D6 advagg + D6 cdn modules leave Drupal referencing CSS image links [via CSS background: url()) as relative links to the root of the host (CDN or other).
So with the way it was, CSS image links refer back to the parent [host] - not the actual image asset path!
When using my CDN (edgecast), without my above 'base-url' hack to advagg, the CSS relative links attempted to query my CDN's root domain - rather than the actual [full] path.
Actual example: my Edgecast CDN paths are:
I do NOT elect to use CNAME mapping (via Edgecast CDN)
So when I used the 'untouched' D6 advagg + D6 cdn, the final CSS has relative url links back to http://small.gdlcdn.com, this is a simple domain link - and NOT a full [absolute] path to the actual CSS image asset. Hence, the 'untouched' advagg + cdn breaks all my relative CSS image links. That is normal for most Drupal CSS that I have yet seen.
My above 'addition' - via the standard D6 core method does not. Hence, I 'hacked' this logic into advagg, for it is currently responsible for the creation [re-writing] of CSS - not so with the CDN module.
Yes, I have allowed Wim Leers to be 'privy' to this too.
Comment #4
mikeytown2 commentedWhat your looking for is a path prefix for the CSS url() references. If you add
/802C5F/cdn1to the start of every path it should work (no need to use absolute urls). The CSS Embedded Images module isn't doing anything for you because your using absolute references; the path prefix needs to be added after CSS Embedded Images has modified the CSS data.Heads up your only using 1 CDN at the moment (
http://small.gdlcdn.com/); so the cdn1,2,3,4 configuration isn't doing much for you. Shouldn't your configuration look like this:Where
cdn2.peterbowey.com.aupoints tosmall.gdlcdn.com/802C5F/cdn2. This way you don't need$conf['my_cdn_css_base_url']and you will benefit from parallel downloading from different domains; and you don't have to hack advagg then.Comment #5
mikeytown2 commentedWill need to run each image in the CSS through advagg_build_uri so that cdn_file_url_alter()/cdn_pick_server() function runs. And to support your special one off case (if you still desire it) have the ability to prefix the path; your one-off case will be a
$conf['']setting though; no GUI for it because it is rare.Comment #6
Peter Bowey commented'Eh' #4 that mapping would point CDN assets as myself,so no! (?)
The mapping of all http://cdnx.peterbowey.com.au is the private [back-link] path that the commercial Edgecast CDN pulls new aggregates from (via public web links thru small.gdlcdn.com/802C5F/cdnx)...
Need more coffee :)
Comment #7
Peter Bowey commented#5 Nice being 'rare + one of'...case!
Are you sure on this? The only difference in my use of the commercial Edgecast CDN is dropping the use of CNAMES to get a domain - instead of my chosen domain + path...
Comment #8
Peter Bowey commentedHmmm... coffee helped!
I see that you are suggesting the use a prefix' relative path to the CDN domain [use].
Hence, I would use:
Does this new relative method 'satisfy' the CSS Embedded Images module?
Comment #9
mikeytown2 commentedNope; the prefix trick needs to happen after CSS Embedded Images module runs.
Comment #10
Peter Bowey commented#9 Is that stating I need such mapping (as above) to occur in the right code area of advagg?
IE: Do I need to 'hack' advagg to do catch correct event chain..
Comment #11
mikeytown2 commentedIf I create a module that has a heaver weight then CSS Embedded Images and uses hook_advagg_css_alter; then no need to hack advagg.
As for your cdn settings; have
small.gdlcdn.com/802C5F/cdnXpoint topeterbowey.com.auas the source. HavecdnX.peterbowey.com.aupoint tosmall.gdlcdn.com/802C5F/cdnXin the DNS records; and use the configuration in #4. If you don't do this then all thecdnX.peterbowey.com.audomains are pointless as well as any of thecdnXstuff because the browser will only hitsmall.gdlcdn.com. Having different paths on thesmall.gdlcdn.comdomain will gain you nothing; it only adds unnecessary complexity; having thecdnXpaths point to different domains does nothing as well.Comment #12
Peter Bowey commentedThanks Mike,
#11 makes sense light of where to 'hook' my code needs; I use the hook_advagg_css_alter within a new module with +weight (=bingo).
The rest of our 'cdn references /data chat' is likely 'not of important context' - not without a long open debate :)
So we will ignore that part' - for a bit :)
Comment #13
Peter Bowey commentedRefer #11
I took the 'lazy code path' and moved my previous advagg 'hack'
It now does the path 'prefix' after 'hook_advagg_css_alter'
Works OK
Comment #14
chriscalip commentedI liked the idea so much that I made a module out of it and planning to use it for most of my sites. Thank you peter and mikey!
http://drupal.org/project/parallel_css
Module provides an admin interface where you can put in the domains to be used in the css aggregates.
Comment #15
mikeytown2 commentedMoving this to #1182670: Integrate with the CDN module
Comment #16
wim leersReopening to get feedback.
As of #1452092: Automatically distribute certain filetypes over multiple CDNs, the CDN module now overrides CSS aggregation (on both D6 and D7, but on D6 only if the AdvAgg module is not enabled). The Parallel CSS module made sense, but now I think it's time to get rid of it and simply use the CDN module instead: #1410318: Merge into CDN module?. Corresponding CDN issue: #1452092: Automatically distribute certain filetypes over multiple CDNs.
Basically, it will mean this: *every* file URL in a Drupal site, also those in CSS files, will be altered to point to a CDN, according to *one* set of rules: those of the CDN module. Simplicity. Bliss. Less modules to consider, install and maintain.
I also just pinged @chriscalip.
Comment #17
mr.j commentedThis does not currently work for me. Relative paths in our CSS files are not changed by CDN. See issue here:
#2153417: CSS url rewriting
Comment #18
mikeytown2 commentedLooks like this was fixed in the CDN module