Templates & Renderers
One of the great things about Marionette is that it doesn’t force you into specific libraries or coding styles. In this blog, I’ll go through some different template engines and how we can setup Marionette for each rendering engine.
For those who want to customize their rendering pipeline even more, maybe providing alternative caching techniques or global mixin capability, we will take a brief look at the Marionette Renderer and some of the interesting results you can get if you customize it.
Templates
If you’re relatively new to web development, templates are a file or string that turn your code and data into a static output, such as HTML for your browser. Let’s look at a quick example using the built-in template language for Backbone:
In this short example, we populate a title
attribute and a list of items
. When we compile the template, we get a function back that will output the expected HTML once we pass some data in.
Template Engines
JavaScript has a plethora of templating engines with different strengths and weaknesses. Luckily for us, they all have the same high-level API: template('someString')({key: 'value'});
returning a string. The major differences are in the template syntax. The three we’ll look at are:
Underscore/Lodash
This template engine comes free with Underscore and Lodash and — thus — free with Marionette. Underscore’s template syntax has three base constructs:
<% %>
executes the JavaScript inside the brackets<%- %>
outputs and escapes the result of a JavaScript expression<%= %>
outputs without escaping the result of a JavaScript expression
Let’s check out our favourite note-taking example to cover all three structures:
Handlebars
Handlebars is one of the most popular JS template engines out there. The closest analogue is Jinja and the Django template engine. Handlebars has more syntax
There’s a bit more setup needed here to setup the markdown
function to run for Handlebars. Unlike Underscore, you need to register any helper functions to make them available to your Handlebars templates.
Pug
Pug (previously known as Jade) is a powerful templating tool that uses its understanding of HTML to build your HTML.
Pug’s syntax resembles Python in its use of indentation for scope — other template engines can quickly get unwieldy if you aren’t disciplined about how you write everything.
Configuring Your Engine
Configuring your template engine can be done in two places: within your app or in your build tool.
Configuring in Your App
This is the easiest way to setup a template engine – just pass in the template function as the template
argument. We’ll look at an example using Underscore’s template engine:
While this way keeps things a bit simpler — you don’t need to create new files for templates — anything over the simplest templates requires the browser to take time compiling your template string into JavaScript code to execute.
Configuring at Build Time
Most of the time, you’ll want to configure your template engine to run at compile time. This will pre-compile your template files and strings into the JavaScript code that will build up your HTML output. As Webpack is currently the most popular build tool, we’ll look at an example webpack.config.js
with the different options set for each template engine.
Before configuring Webpack, make sure you install the necessary template loader.
For Underscore/Lodash
npm install underscore-template-loader
For Handlebars
npm install handlebars-loader
For Pug
npm install pug-loader
Using the template loader, we can now just import templates as regular JavaScript modules, pre-compiling them when Webpack builds your bundle file:
As you can see, setting up a template engine with Webpack is fairly straightforward.
A Word on Renderers
I promised to enlighten you a little more about customizing your renderer and some of the benefits you can get if you do so. Renderers are usually used to handle the actual template rendering and caching pipeline, for example implementing a template engine such as Handlebars, however we’re not restricted to doing that.
Let’s take a really simple example and mixin some methods that could act as global template helpers (or templateContext
):
In this simple example, we can now access the date in any template and format any data however we please, without having to mix it into every single template.
Conclusion
Marionette provides some options for building your templates out. The documentation in this area is pretty decent and covers more areas than I can do in a simple blog post. Hopefully this should give you a few ideas for when you come to start building your app and some boilerplate to get you started.