mod_rewrite FTW

February 10, 2012 - Michael Millett

The rewrite of Discount Tire's website wasn't executed as a 'responsive' design. While that term is starting to gain a lot of traction today, when we started development nearly two years ago, it was a bit more esoteric. The concept felt right, ideal even, but there was very little industry experience with it. In fact, when I showed the demo I'd made to folks around the office, most had never seen anything like it.

We took a different approach. A hybrid of some responsive concepts and a more traditional 'm.' dedicated mobile site. When many people think of or see an m. in the domain these days, there may be an assumption that the site is a stunted and dumbed-down version of what the 'desktop' experience would be. Not the case for our site.

Both the www and the m domains in the Apache configuration resolve to the same document root, and for us, the same application proxy. It is the same code base generating (mostly) the same markup, regardless of the domain the visitor is on. In this way, the site doesn't behave like a typical m. which runs its own crippled version of the proper site, instead of just being the proper site. There are some optimizations within the pages as well. For instance, most extraneous marketing material, oversize graphics, etc. are simply not sent to browsers on the m. domain.

With a responsive design, you have a couple options. There is only one version of the actual HTML document. This means you choose whether to deliver desktop content, or mobile content. If your content is the same for both, I'm envious. Our desktop site is made of mostly critical content, bedazzled with more misplaced marketing distractions than I'd like. However, those distractions are considered critical content to many folks in the organization, so they stay. On mobile we can get away without showing them, so we don't. But that brings me back to the one HTML document issue. If we're going responsive, we have to choose which is the truth, and which is the clone.

If we say the desktop is truth, then the markup will be littered with stuff that the mobile experience will conceal. The file will be bigger to download than it needs to be. If we say mobile is the truth, and progressively enhance to add the marketing fluff after the fact on desktop only, well then our javascript disabled users won't see it. I'd be fine with that, because again, I don't have the highest opinion of it's worth in the first place. But that's not the point. At the time, the majority of our user base was on IE8 and IE7, where responsive design is javascript dependent. Enough of that same user base visits our site with JS disabled that it just didn't seem worth it to have to make the tough decision about what's the truth...if we didn't have to.

In the java code, we use the request's host property to determine what CSS and JavaScript files should accompany the HTML that is generated. We also use it to optimize the content itself. This is a nice benefit to doing it the way we did, and pretty much works as simply as this:

if(subdomain == 'm.'){     <link href=​"/​path/​to/mobile/main.css" … >​   }
if(subdomain == 'www.'){   <link href=​"/​path/​to/desktop/main.css" … > ​ }

It did pose a problem of its own though. Not every single page of our site is part of the java application. There are a handful of static .html files that need to use the mobile stylesheet on the m. domain and the desktop stylesheet on the www domain, just like the rest of the creaking coggery of the main application. HTML itself doesn't offer a means to make programatic decisions at run time, so what to do?

Enter mod_rewrite

To solve this issue, we settled on developing a new file structure for the types of assets affected by this (stylesheets and javascript mostly). The structure looks like this:

      dtc.css (optimized for large screen)
      dtc.css (optimized for small screen)

mod_rewrite then executes the following rules:

RewriteCond %{HTTP_HOST} (www)\..+\.com [NC]
RewriteRule ^/assets/css/(.*) /assets/desktop/css/$1

RewriteCond %{HTTP_HOST} m\..+\.com [NC]
RewriteRule ^/assets/css/(.*) /assets/mobile/css/$1

This allows us to use one resource reference...

<link href="/assets/css/main.css" rel="stylesheet"/>

in a static file, with no inherent preference for mobile or desktop, and apache will handle routing the request to the appropriate version of main.css. As long as two files are identically named, one each in /desktop/css and /mobile/css, we can access them using /assets/css and trust we'll get the right one. Even if the page in question can't execute logic on its own.