IE8: disco dev

It’s weird, when I looked up the most important historical events of 2009 I couldn’t find any mention of Microsoft’s release of Internet Explorer 8.

Some of our ilk work at companies where we build software for humans whose Gateways and Toshibas are allergic to foxes and canaries, and safaris are for yacht-club members only.

Back-end (or “butt”) programmers are lucky. They are spared from building web from inside a time dilated vacuum, where your app runs on like 10 runtimes from throughout human history. At minimum for us my current employer Science Exchange:

IE8, IE9, IE10, IE11, Chrome (latest), Firefox (latest), Safari (latest), Mobile Chrome (Android 2), Mobile Chrome (Android 3+), Mobile Safari.

Ugh, x-browser support is the dialectic of Moore and Murphy’s laws…

Computer languages evolve quickly like IRL languages so even Brendan Eich’s broken version of Node.js from 1995 and the port of Adobe’s Photoshop’s palette (later dubbed “CSS”) are on fleek; and I literally can’t. And neither can’t IE8. Even Satya Nadella gave up trying to use :last-child so he‘s officially shutting IE8 down at the start of 2016 to finally live on the Edge.

Equalizing the UX for our enterprise and academic users is a gritty problem; involves a kaleidoscope of strategies, workarounds, polyfills, shims, and hacks. Idiosyncratic, colorful, multiplicitous is the sunny side.

The struggle is real if you want nice things

Generally if you are a good CSS writer and don’t require the use of many modern tools, your layouts won’t suffer too much in IE8. I mean, even box-sizing: border-box is partially supported (save for using min/max width/height). And if your brand stewards are cool with sacrificing rounded corners, maybe life is relatively chill in your codebase.

Let’s talk through some of the major headaches I’ve encountered in recent battles with ghosts of christmas past:

Media queries: your site everywhere but broken in older versions of IE everywhere

Alas, media-queries — so incredibly useful to building responsive. But entirely unsupported in IE8. Try opening a browser in your VM. Then die a little inside.

Fortunately, the handsome responsive whisperer Scott Jehl has developed a library called respond.js which will save you a complete rewrite or rethink of your CSS. Especially useful if your preferred style is scoping media-query declarations alongside your “default” declarations for your components, modules, blocks (however you meaningfully group your css).

Respond.js is a pretty insane polyfill that re-requests CSS from the server, rips out the media queries rules with a couple regex runs, and then appends those styles to the <head>. You might be familiar with this technique if you’ve used the Selectivizr library for polyfilling CSS3 selectors.

The only downside I’ve observed using respond.js is a bit of FOUC on a slower connection. In our case we were willing to accept a little FOUC (just wanted to say it again) as a tradeoff with refactoring our media-queries out to separate files — which would add an additional maintenance burden in the future to replicate responsive component classes across these files per each breakpoint.

Unlike other polyfills, installing respond.js isn’t a simple copy/paste op due to CORS considerations for assets that live on a CDN. So I put together a quick, Rails-oriented guide based on instructions from the README:

  1. Assuming you downloaded the zip from Github, add the respond.js file to app/assets/javascripts/vendor directory.
    (There are a couple of respond-rails gems out there, but I opted for standalone incorporation to have more control debugging.)
  2. Add the respond-proxy.html file to your app/assets/ directory.
  3. Add the respond.proxy.js and respond.proxy.gif files to your public/ directory.
  4. Depending how your framework builds links to precompiled assets on your CDN, you might need to write a small convenience method to load files directly from your domain. In our Rails app we built this small utility:
def local_asset_url(asset, request)
“#{request.protocol}#{request.host_with_port}/#{asset}”
end

5. For code clean-ness, create a partial that will bootstrap the respond files in your template. Something like:

https://gist.github.com/rosschapman/6cb5fa1d5b48b8e311d2

6. And finally, deploy.

CORS: careful when using third-party libs that do hard things

Speaking of cross domain requests.

Algolia powers search at Science Exchange. Now, we like Algolia a lot, from API to docs to web interface. But if you were running v2 of their JS client a short time ago (or still are), you may have glossed over the part in the instructions explaining how to turn on JSONP for CORS requests. And then you probably spent some time wondering what the eff was going on during browser testing when IE8/9 just completely died.

JSONP is a sneaky workaround for same origin policies which use <script> tags to request JSON-formatted content, wrapping the JavaScript “response” in a function. Which defies the domain limitation. It’s an especially useful approach for older browsers like IE8/9 which do support CORS, though heavily restricted.

So, you’re jiggering Algolia, but if you omitted this line, like we did…

opts.jsonp = true

…well, console throwing Pantone Solid Coated 485 C. Requests access denied and seemingly no escape hatch in while Algolia’s JS client maytags in an endless retry. Then fans whirring. Lockdown. Death. Ugh, restart VM.

Props to Algolia, though. In v3 of their client they automatically detect CORS support and opt in for you. Probably just as much overhead to do a browser check vs having API consumer set a config. And from what I could tell by some cursory glances in the source, they already had boilerplate for these x-browser checks in v2. For example:

var support = {
hasXMLHttpRequest: ‘XMLHttpRequest’ in window,
hasXDomainRequest: ‘XDomainRequest’ in window,
cors: ‘withCredentials’ in new XMLHttpRequest(),
timeout: ‘timeout’ in new XMLHttpRequest()
};

The value here returns false since the “withCredentials” is not available until IE10. Old IE identified.

Console: debuggers causing bugs because meta

This is one of the quirkiest x-browser testing issues I’ve encountered over the years. Up there right with stylesheet limits. Stylesheet limits? Yeah, like <IE9 will quit parsing any CSS after the 4095th rule per file. Dangerous if thy sheets are concatted all together without a sophisticated module system like Google has: https://www.youtube.com/watch?v=vAs9tjEkkKk.

Anyway, as this tale of woe goes, I’m staring at the screen trying to figure out erratic behavior on the page where sometimes a search input dropdown menu fires upon keypress, sometimes not. Soon, I begin to notice a pattern. The JavaScript is only executing when I have IE’s dev tools open. WAATTT?

Get ready for this. Took me some very wild luck googling for this explanation.

Turns out while IE8 does support the console object, it only instantiates the object after dev tools has been opened. Sigh.

Therefore any errant console.log(…) statements in your code will totally kill JS execution. You might already consider the use of console object to log warnings, errors as bad practice primarily because implementation is non-standard across browsers — but did you ever think it would just destroy your work entirely. I was even reading recently that using console.* in async routines can be totally unpredictable. For example, certain runtimes might defer console.log(…) I/O to the background while performing another operation so the observed value is logged incorrectly — the logging call is completed too late. If you weren’t convinced before, leave debugger statements out of your production code. Throw or be poetic and die silently like a warrior.

We had a few loggers sitting around in some old admin tooling code from before we had linting as part of our CI suite. Killed those. Also, for extra protection against threats from third-party code that might irresponsibly use console, add this to your main application template:

Boss defeated. But this was a gnarly hour or so of time spent programming for the past.

Hail the problem solvers

Kissing the ass of old browsers is not delightful. You just have to remember that you’re a problem solver and this is just another problem. Users come first, and we build for all of them.