post image is from here

Giddy Up Go, Drupal

Now that we've figured out what buckets things belong in and how to serve them, we need to spend a little time teaching our favourite CMS how to take advantage of our new setup. This post is entirely Drupal-specific so if you haven't seen the light or aren't curious about how easy it makes things, you may want to skip ahead to the next in the series, setting up a hybrid Apache+Nginx environment.

This is usually where you hear people swearing and banging their heads against their desks as they struggle to get the right balls coming out the right holes but ages ago you, dear reader, made the right decision and picked Drupal. While it's true you can use the CDN module, I chose to roll my own because, well, it only takes about a dozen lines:

$_URLER_RX = '/\.(css|js|jpe?g|png|gif|ico|svgz?|ttf|otf|woff2?|eot|html?|txt|swf|gz|json)$/';

function urler_file_url_alter(&$uri) {
    global $_URLER_RX;
    $server = $_SERVER['HTTP_HOST'];

    if( strpos($uri,'http://') === 0 )

    if( strpos($uri,'js/wysiwyg') === 0 )
        $uri = 'public://'.$uri;

    if( file_uri_scheme($uri) == 'public' )
        $uri = 'http://content.'.$server.'/'.file_uri_target($uri);
    else if( strpos($uri,'assets/') === 0 || preg_match($_URLER_RX,$uri) )
        $uri = 'http://static.'.$server.'/'.$uri;

First, if a fully-formed URL wanders in to our function, we bail because it's probably best that we not tinker with it. Also, we want to make 100% sure anything the WYSIWYG module generates stays specific to this site, so we force it to come from public://, which is our content bucket. These files rarely (if ever) change so it's no concern they get a super long TTL.

Next, anything living in public:// gets pointed to content. This ensures that all of the larger assets (ie the images, videos, etc) we upload and any derivatives that get generated wind up being forced to 1 year expiries, which is pretty much as high as anybody ever seems to go.

By doing this way, we ensure our heaviest assets live in either our CDN of choice or the browser's cache for for as long as possible, which means we have to serve them as little as possible.

Finally, we check if the URL ends in a file extension we recognize and make sure it comes from static. The astute among us will notice this is pretty much the same expression we use in our .htaccess.static and, well, it is.

After you've dropped this function in to a module of your choosing (and updated the hook's name, of course), start browsing around your site and tweak both the module and static's regular expressions as needed. The list of extensions I use works for me but, as with everything else, YMMV.

Now that you've had a chance to look things over, you might be thinking "Hey, Jaypo, when I turn on JS and CSS aggregation, there aggregated files wind up in the 1 year TTL bucket." Yup, since they're files generated by the CMS the wind up in files/, which is perfectly valid, just not desirable given how we're using it. So how do we move them?

Enter the Advanced CSS and JS aggregation module (AdvAgg). Among the myriad useful things this module does (and I highly encourage you to play around with its various options), it allows us to specify another directory for the aggregated files. I choose assets/ right off the web root, partly because this makes them come from static, partly because I run multi-site and AdvAgg is smart enough to use similar module and system aggregations it's already generated for other sites. 

Yup, you read that right: One site can save the same aggregate being generated by every site you're hosting. If that sounds attractive (and it should), continue on to the child page, otherwise jump down to getting a hybrid Apache + Nginx (or Apache + Apache proxying to Nginx, if that's your thing) setup kicking.