Thursday, 5 September 2013

Beware - Knockout & Containerless bindings!

For quite a while now, we'd heard reports of a strange bug occurring on our live servers that was causing users much frustration. The 'Apply' button (quite an important button on a job-board) was simply not showing for a very small, but vocal number of users.

There is actually an element of complexity surrounding the apply button - given we have some fancy spell-checkers & other scripts that need to initialize before the user can be able to apply - we have a little loading swirly that only enables the button once said assets have loaded (this is better than the user clicking the button, only to have it do nothing).
99.9% of users never even notice this, as it is normally shown within a fraction of a second.

Why was this breaking for some users?

Frustratingly, this issue could never be recreated by any of the team. We had tried testing in all of our test environments, on all of our test devices... iPhones, iPads, Android, Windows, Mac - we tried testing against simulated slow connections... - we tried everything we could think of - to no avail.

The Issue

For some time, we have used the fantastic Knockout library in our client-side code, to allow us to develop complex and interactive interfaces, by leveraging the MVVM programming pattern.
As-is normal in such a programming style, a model is defined, containing all of the requisite data and then this model is applied and bound to the document, with something like:

    ko.applyBindings(this.viewModel, $("#container")[0]);

Unsurprisingly, if the call to applyBindings() fails for any reason, then an exception will be raised, terminating the execution of further script. We added some additional logging to our live environment, and were able to determine that this indeed, was what was happening to a small minority of users in our case.

Importantly, our customer support team were able to narrow-down the effected users to those who were using 3G-based internet connections... Why was this important? We had no idea - however - we were finally able to recreate the issue (albeit only via 3G connections to our live servers).

Upon looking at the console dump from our live servers - we could see the issue.

Knockout allows a tempting style known as 'Containerless bindings' wherein a template is defined using HTML comments, as below:

    <ul class="drop-down-menu">
        <!-- ko foreach: itemsToBind -->
        <!-- /ko -->

I'm sure you've probably guessed what's happening now - that some mobile networks (at least O2 in the UK), assumedly in an effort to reduce the amount of data transferred may actually choose to strip out HTML comments via their proxies before the serve the document to a client.

An easy fix, was to simply replace these bindings with:

    <ul class="drop-down-menu" data-bind="foreach: itemsToBind">

Long story short - you can't rely on HTML comments appearing on any client devices - so don't write code that depends on them!

1 comment:

  1. Was it their carrier, or was it their browser? Some browser like Opera Mobile (or is it Opera Mini) have some optimization settings which proxies all web traffic through their servers which "compress" web pages. Amazon's Kindle Fire also has a similar feature.