The Marketing Technology Office

Perils Of Open Source Software

Content Engineer DJ Gilcrease

We here at Kanban love Open Source code and attempt to use it wherever possible. This is much easier on the frontend (HTML, JavaScript, CSS) than it is on the backend (Depending on your platform of course). In almost every frontend project we have worked on we have automatically included one Open Source JavaScript library: jQuery.

In a recent project, one of our goals was to speed up page load & rendering time on the product listing and detail pages (The product detail page used to take 15 seconds to render). One way to do this is to dynamically load in data/DOM only when it is needed. Doing so either required the backend to learn how to render data for each section separately, or to use frontend templates. With the particular backend system we are using, making it learn how to render each section individually would not be worth the effort, so we settled on jQuery Templates[1].

Even though it was in beta, it was being officially backed by the jQuery team and Microsoft. Though we understood that beta software would have bugs, it was an acceptable risk.

The first bug we experienced was with templates that called other templates. The code was designed to not allow more then 1 level of nesting on templates (template1 -> template2 !-> template3) as they automatically assumed the second level was a function call.

This was a relatively easy bug to fix: just check before you call that it is indeed a function and send it though the template parser again if it is not. And like any good Open Source citizen, we filed a bug report and supplied a patch[2].The second bug we experienced was with their parser and the way we had done some function calls. Several of the functions we wanted to call took an object as a parameter, and the contents of this object were being built with data being passed into the template:

    <script type="jQuery/template" id="template1">
        {{if $data.variants }}
            {{each $data.pnos_m_et }}
                {{tmpl({array: $data.pnos_m_et, value: $value, obj: $data.variants[$value]})
                                brand.cft.templates.c48.tile_view.block }}
            {{/each}}
        {{else}}
            {{tmpl({array: [], value: null, obj: $data}) brand.cft.templates.c48.tile_view.block }}
        {{/if}}
    </script>

We initially tried to allow nested objects {array:[], value:$value, data: {name:$data.name, other:$value.something,…}}, but this broke their parser, because it was based on paired {{ && }}. So we accepted this and reworked things a little to ensure we never needed to pass nested data structures. This worked for a while, but then we got to the point where the template code itself would need to call some form of initialization function when it was injected into the page, and we did not want the code that was injecting it to require knowing what was being injected. So we tried adding code at the end of each template that looked like:

    <script type="jQuery/template" id="template1">
       …
         <div class="script">
            {{=
                jQuery.tmpl_queue.add(function() {
                    nikon.normalizeProductTileHeight({
                        "id": "{{data.id}}",
                        "region": "product-details"
                    })
                })
            }}
        </div>
    </script>

But again this broke their parser, as you could not have a line break between {{ && }}. So at this point we sat down and looked at their parser, and looked at other javascript template systems: JavaScript Micro-Template[3], Pure[4], and EJS[5]. We did not want to go back and have to manually update ~1500 JavaScript templates, but we liked how JSMT & EJS were using <% && %> as their section identifiers. A quick test of that showed that the simplistic XSLT engine our backend uses would break if there were any < || > that were not part of a tag, so we settled on {% && %}.

We spoke privately with the jQuery Templates team and they did not like this, because supporting the type of code we were trying to write was outside their goals. So we just modified our local version to support this. To make this backwards compatible we added another regex that matched our new opening and closing tags. We also set it up so that it would do console.info calls for every template it parsed that was using the old system, so if we happen to be working in an area using old templates we could see that and update them as we go.

So far we have only addressed known perils, bugs, and project divergence due to use-case differences. The major peril of Open Source Software is project abandonment. Two months after all the work was finished for us to be able to use jQuery Templates the way we needed to, the jQuery Templates team decided to abandon the project in favor of including templates in jQueryUI at some future date. So for the time being there is no official template support for jQuery, and we are left supporting code for a client that we expected to have external support and bug fixes for. [1] http://api.jquery.com/category/plugins/templates/ [2] https://github.com/jquery/jquery-tmpl/pull/77 [3] http://ejohn.org/blog/javascript-micro-templating/ [4] http://beebole.com/pure/ [5] http://embeddedjs.com/

Back To Posts