14

I'm splitting up one of my larger apps and introducing a 'cdn' url to house common objects like CSS, javascript, and images to avoid duplication. What I need to do, though, is have separate URLs for our dev environments, so I may have:

http://cdn-dev.example.com
http://cdn-qua.example.com
http://cdn.example.com

depending on what environment we're working in. I can get this to work for things that are generated by our PHP code, but I'm at a loss for the .css and .js files that will be called. For example, how do I make something like:

.cool-button { background-image: url('http://cdn.example.com/images/button.png'); }

switch between the different domains?

What's the best way to deal with that?

[EDIT]

Just so everyone is clear, the CDN address is a different domain that the site. So, the dev site might be http://www-dev.domain.com which would use http://cdn-dev.domain.com

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
dragonmantank
  • 15,243
  • 20
  • 84
  • 92

9 Answers9

26

Use relative paths, not absolute paths. When inside a CSS file, the path is relative to the CSS file and not the HTML page.

If your CSS file is here

http://cdn.example.com/css/style.css

And your class is

.cool-button { background-image: url('../images/button.png'); }

Then the browser will attempt to load the image from

http://cdn.example.com/images/button.png
great_llama
  • 11,481
  • 4
  • 34
  • 29
  • Usually I'll put the images folder under a CSS theme folder, though, as it allows me to use image names that aren't specific to a particular stylesheet document. I would be able to have a button.png under /this_theme/ and the same file name under /that_theme/ and the class definition could remain the same. – great_llama May 13 '09 at 16:03
  • Don’t confuse relative/absolute URI paths with absolute/relative URIs. Because `/css/style.css` is an absolute URI path but a relative URI. And `http://cdn.example.com/css/style.css` (beginning with `http://`) is an absolute URI but not an URI path (it just contains a URI path). – Gumbo May 13 '09 at 16:08
  • 2
    Of course, this only works if you host the css file on the exact same domain as the images, which is often not the case – travis-146 Jun 10 '09 at 14:56
  • 1
    Why bother hosting stylesheet-related images on a CDN and not the stylesheet itself? – great_llama Jun 10 '09 at 19:10
6

Just use domain-relative url's?

.cool-button { background-image: url('/images/button.png'); }

Then the browser will look under the current domain.

gnud
  • 77,584
  • 5
  • 64
  • 78
2

You can also have a build process and use templates to generate environment specific files

e.g. in a file called yoursite.template.css

.cool-button { background-image: url('@@URL@@/images/button.png'); }

create the yoursite.css file than replace @@URL@@ with the domain you want.

Robbie
  • 209
  • 1
  • 3
  • 10
2

Depending on your server configuration, you can also append the .php-extension to your filenames and have them treated as PHP scripts too:

I.E.: style.css.php would contain:

.cool-button { background-image url(<?php echo $bgImgUrl;?>); }

This also works for JavaScript-files.

Christian Studer
  • 24,947
  • 6
  • 46
  • 71
1

Searching for an answer to this too, I saw a simple one: create your css file with duplicate classes, one for scenario 1 (images load from same domain) and another for scenario 2 (images load from CDN).

e.g.

.container {background-image:url(my/site/image.png;)}
.container-CDN {background-image:url(http://my.site.cdn.com/image.png;)}

Then on your index.php introduce PHP to call the correct class

e.g.

<body class="container<?PHP if ($whatever) {echo "-CDN";} ?>">
newyuppie
  • 1,054
  • 1
  • 8
  • 13
1

I've literally just been working on the same thing today and here's what I came up with.

Stick this in your .htaccess file in the root of your site. This obviously relies on Apache and Mod_rewrite.

RewriteEngine on
RewriteBase /

# Redirect content to the CDN

RewriteCond %{HTTP_HOST} !^cdn\.server\.com$    [NC]
RewriteRule .*\.(jpg|gif|png|flv|css|js|swf)$   http://cdn.server.com/$0    [R=301,L]

This will send requests for the file types in the brackets to your cdn and keep requests for other types on your primary server.

Greg B
  • 14,597
  • 18
  • 87
  • 141
  • Doesn't that defeat the purpose of the CDN? It means the client has to still contact your server for every request to the CDN, versus hitting the CDN directly. – davr May 13 '09 at 16:18
  • True, but the content will not ne served from your server. So instead of a 5Mb FLV being delivered from your server. It will be redirected to the CDN where the actual download will happen. This configuration allows you to easily swap from a single server development environment to your live environment without any changes. I'm not advocating this as _the_ way to do it. It works for me and the miniscule roundtrip for the 301 is worth it. – Greg B May 13 '09 at 17:31
  • How would this work if you had some files on the CDN and others locally? – dragonmantank May 13 '09 at 20:00
  • It wouldn't. This is just one example that worked in my situation – Greg B May 13 '09 at 20:08
0

If the server is same, you can use relative paths. Like /http/blah/test/images/button.png or ../images/button.png

NinethSense
  • 8,824
  • 2
  • 23
  • 23
0

When using relative URLs, you can force a "base" url. In the <head> tag, use <base href="http://cdn-dev.example.com">. Then, every relative link "/style.css" will point to "http://cdn-dev.example.com/style.css"

For reference: http://www.w3schools.com/TAGS/tag_base.asp

  • 1
    But this has also disadvantages. For example, URI references with just a fragment identifier `foo` will then be resolved to `/#foo` and not just `#foo` in the same document. – Gumbo May 13 '09 at 16:15
0

Well...the solution I came up with was...sorta...hackish, ugly and dumb. But, hell, it worked:

<?php
    if ($_SERVER['SERVER_NAME'] == "www.domain.tld") {

        $incs_path  = "/usr/local/psa/home/vhosts/domain.tld/non-web-root-folder/private-files";

    }
    else {
        $incs_path  = "incs";
    }

require_once "$incs_path/$file-to-be-called.inc";

?>

This is, as noted, hacky and ugly and could be done far more prettily. But it does, at least, allow you to define specific locations for specific groups of files depending on the host.

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • and domain-relative urls would, probably, be far prettier and more useful. My suggestion, I guess, is more useful for linking to otherwise private information (I tend to use this kinda thing for db passwords and such for web apps). – David Thomas May 13 '09 at 16:14