SAVE 25% when you purchase our Theme Bundle and Make Plus together. View bundle deal.

Backbone.js and Collections: Structure

By Zack Tollman on September 10, 2013

Earlier this summer, we launched Collections, the first WordPress theme that we know of that leverages Backbone.js to add single page application (SPA) experiences (e.g., load new content without a full page refresh) in the theme. Now that the theme is in the wild, I would like to share some of our experiences building the theme through a series of posts about Collections. These posts will specifically emphasize the integration of Backbone.js into the theme.

At the outset, we decided that the SPA features would follow the progressive enhancement philosophy. First and foremost, we wanted to build a solid WordPress theme. Then, we wanted to make it special by adding SPA features on top of it (e.g., fast page loading, transition animations). Fortunately, this approach paid off as we were able to create a WordPress theme that did not need to compromise WordPress standards in order to implement SPA features.

A bridge between two worlds

Collections is structured similar to any standards compliant WordPress theme; it contains CSS files, template files and PHP files that implement additional functionality. It works as a normal theme if the files that implement the SPA are removed.

The SPA features are established via three PHP files and nine Javascript files (which are concatenated and minified into a single file for the release builds). One of these files provides routing for a JSON endpoint. If a request for a page has the cspa-json query variable appended to it, it will cause the content to be rendered via a template file that provides a JSON representation of a post or archive. This second PHP file renders all of the post’s data in a JSON object. The final PHP file handles enqueueing JS files, manages JS template files, and provides extra support for JS functions.

Collectively, these three PHP files provide the bridge between the server side WordPress application and the client side SPA. These files expose the server side components of WordPress that are needed on the client side.

Did you know that Surf Office, Postmatic, Yeah Dave, and over 700,000 small businesses run their websites with Make, our free WordPress page builder. Discover the Make page builder now.

Templating for PHP and JS

In addition to adding these PHP files, template files are modified to work both as a WordPress template and an Underscore.js template.

Page views that are loaded without a full page refresh require Underscore.js templates. Since these templates use HTML identical to the PHP version of the template, we aimed to avoid duplicating the templates; instead, we utilized the same template for multiple purposes. For instance, the following code shows a common expression in a WordPress template to display a post’s content:

<div class="standard-content">
    <?php the_content(); ?>
</div>

In order to integrate the Underscore.js template alongside the WordPress template, we modified this code:

<div class="standard-content">
    <?php if ( collections_is_js_template() ) : ?>
        {{{ content }}}
    <?php else : ?>
        <?php the_content(); ?>
    <?php endif; ?>
</div>

If the template is rendered as a WordPress template, the the_content() function will render the current post’s content. If the template is rendered as a Underscore.js template (i.e., collections_is_js_template() returns true), the template will be written with the {{{ content }}} placeholder. When the theme loads this template via JS, the {{{ content }}} placeholder will be replaced by the actual content.

Progress

Other than these changes, the theme operates as a normal WordPress theme. We adhered to the progressive enhancement philosophy with this theme. We built a WordPress theme and then enhanced it by building a SPA on top of it.

In the next part of this series on Collections, I will discuss how this structure, along with the requisite JS files, combine to enable the SPA features in the theme.

Enjoy this post? Read more like it in From the workshop.

19 Comments

  1. Russell Heimlich

    Did you ever consider serving up pre-rendered markup instead of JSON + JavaScript templates? The markup could be handled entirely with PHP and there would be less work needed on the frontend since you’re just injecting HTML into the DOM once instead of compiling the HTML using JavaScript. It just seems to be a simpler, easier to manage way to go.

  2. Zack Tollman

    Justin Tadlock: Thanks a lot! Part 2 will start getting more technical.

    Russell Heimlich: Yes! We definitely did. In many ways it would be easier. If ended up going this route, we likely would have used PJAX instead of Backbone.js, which is made for such situations. While Backbone.js lacks a strong opinion and leaves many decisions to the developer, it is fairly standard to request JSON data and render with a JS template.

    All that said, the primary reasons for avoiding server side rendering were speed and control. By rendering client side, we shave a few milliseconds off the response, which is important to us. Additionally, if we get pieces of data back from the server, rather than a big lump of HTML, we have more control over how each piece of data renders client side (e.g., animating elements separately).

    Interestingly, there were situations where chunks of HTML needed to be rendered server side (e.g., comments, “the_content”). I’ll talk more about this when I discuss the difficulties of building a client side application on top of a server side application.

  3. Chris Mccoy

    looking forward to the 2nd part as well, its a great theme to buy if you are looking to dig deeper into backbone as a front end use of wordpress, ive used PJAX in the past to load content, but picking apart the collections theme has been really helpful.

    curious any plans on other themes on backbone? or is this a one time deal.

  4. Zack Tollman

    Hi Chris!

    All I can say is that we really liked how Collections turned out. We really felt that the SPA feel to Collections made a lot of sense. Given the good experiences we had with it, we definitely will consider sprinkling in similar features where appropriate with future themes.

  5. Pothi Kalimuthu

    It’s nice of you to share how you made this theme. Your ideas behind running SPA on top of WordPres theme, may change the way the themes are made in the future. Like others, I look forward to the next in this series too!

  6. Robert O'Rourke

    Interesting stuff. I’m curious if you could use a filter to make certain replacements eg. for the_content(), you could filter the output to display {{{ content }}} no?

    Obviously there are so many cases to cover and a real theme is more complex but for some of the output functions like title etc… could that approach work?

    I’m guessing as well that the loop is handled by backbone now too so will be interesting to see how you go about using the WP_Query object with the js templates.

    Anyway, good stuff – thanks for the write up :)

  7. Zack Tollman

    Hi Robert!

    Great question! This was, without a doubt, one of the biggest challenges of this theme (and I will cover this in great detail later). WordPress gives plugin developers an opportunity to change the post data that is pulled from the database via filters. As such, we had to make sure that when we pulled the data into a JSON representation, each individual piece of data was rendered exactly as it would if the page was rendered server side.

    When the Underscore.js template is rendered and the `{{{ content }}}` variable is interpolated, it is interpolating the *filtered version of the content*. The filtering occurs server side before the data is sent via JSON. If we did not do this, we would break SO many plugins.

    I plan to write a post on the difficult of building a client side application based on an existing app that assumes 100% server side rendering. It will delve into these sorts of issues.

  8. Robert O'Rourke

    Thanks Zack,

    I look forward to it! I’ll have a dig through your collections_is_js_template() function to get my head around the problem. It is a very different way of thinking when you need to have a non js fallback as well, not easy!

  9. gabriel

    please post the second tutorial! i’m very curious about how you approached the routing so that you could use a single template for client and server-side rendering. thanks so much!

  10. Zack Tollman

    Thanks for the enthusiasm! I’m hoping to get to it really soon.

  11. Arsalan Khan

    Great theme! Are you precompiling the underscore templates?

  12. Zack Tollman

    Hi Arsalan!

    It depends on what you mean by “precompiling”. The template is printed in a script tag in the footer of the HTML. When the JSON is received from the server for a new page view, the JS template is retrieved from the DOM and compiled with the received JSON data. Does that help answer your question?

  13. Arsalan Khan

    Hi Zack,

    I have checked the template and you are serving uncomplied templates. I would suggest you to compile and concatenate them and then use for rendering as it will increase the performance.

  14. Zack Tollman

    Thanks Arsalan! I will take a look into this. I see what you are getting at now.

  15. Zack Tollman

    Yup! I’ll be getting to it soon. Thanks for the interest.

Comments are closed.