Overview // MarkoImprove this page

Marko is an eBay open source HTML-based templating engine that can be used to render templates on the server (Node.js) or in the web browser. It is extremely fast and lightweight (~3.75KB gzipped) while also supporting streaming and asynchronous rendering. Developers can extend the HTML grammar with custom tags and custom attributes to introduce new and reusable building blocks. The Marko compiler produces Node.js-compatible JavaScript modules that are easy to read, understand and debug. In contrast to other templating engines, Marko avoids evil global variables and global helpers.

Marko was founded on the philosophy that an HTML-based templating language is more natural and intuitive for generating HTML. Because the Marko compiler understands the structure of the HTML document, the directives in template files are less obtrusive and more powerful. Marko also retains the full power and flexibility of JavaScript by allowing JavaScript expressions inside templates.

Marko supports progressive HTML rendering by writing directly to an output stream so that HTML can be sent over the wire sooner. Marko automatically flushes around asynchronous parts of the template so that the HTML is delivered in the optimized number of chunks. Because Marko is an asynchronous templating language, additional data can be asynchronously fetched even after rendering has begun. These characteristics make Marko an excellent choice for creating high performance websites.

For building rich UI components with client-side behavior please check out the marko-widgets project.

Try Marko Online!

Syntax

Marko supports both a familiar HTML syntax, as well as a more concise indentation-based syntax. Both syntaxes are equally supported. Regardless of which syntax you choose, the compiled code will be exactly the same.

Syntax highlighting is available in the following editors and IDEs:

HTML syntax

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Marko Templating Engine</title>
    </head>
    <body>
        <h1>
            Hello ${data.name}!
        </h1>
 
        <ul if(data.colors.length)>
            <li for(color in data.colors)>
                ${color}
            </li>
        </ul>
        <div else>
            No colors!
        </div>
    </body>
</html>

Concise syntax

The following concise template is equivalent to the previous template:

<!DOCTYPE html>
html lang="en"
    head
        title - Marko Templating Engine
    body
        h1 - Hello ${data.name}!
        ul if(data.colors.length)
            li for(color in data.colors)
                ${color}
        div else
            - No colors!

Mixed syntax

You can even mix and match the concise syntax with the HTML syntax within the same document. The following template is equivalent to the previous templates:

<!DOCTYPE html>
html lang="en"
    head
        title - Marko Templating Engine
    body
        <h1>
            Hello ${data.name}!
        </h1>
        ul if(data.colors.length)
            li for(color in data.colors)
                ${color}
        div else
            - No colors!

Sample Code

A basic template with text replacement, looping and conditionals is shown below:

hello-world.marko:

<h2>Hello ${data.name}!</h2>
<ul if(data.colors.length)>
    <li style="color: ${color}" for(color in data.colors)>
        ${color}
    </li>
</ul>
<div else>
    No colors!
</div>

The template can then be rendered as shown in the following sample code:

require('marko/node-require').install();
 
var template = require('./hello-world.marko');
 
template.render({
        name: 'World',
        colors: ["red", "green", "blue"]
    },
    function(err, output) {
        console.log(output);
    });

The output of running the above program will be the following (formatted for readability):

<h2>Hello World!</h2>
<ul>
    <li style="color: red">red</li>
    <li style="color: green">green</li>
    <li style="color: blue">blue</li>
</ul>

For comparison, given the following data consisting of an empty array of colors:

{
    name: 'World',
    colors: []
}

The output would be the following:

<h2>Hello World!</h2>
<div>
    No colors!
</div>

The streaming API can be used to stream the output to an HTTP response stream or any other writable stream. For example, with Express:

var template = require('./user-profile.marko');
 
app.get('/profile', function(req, res) {
    // Render directly to the writable HTTP output stream: 
    template.render({
            name: 'Frank'
        }, res);
});

Another Templating Language?

Most front-end developers are familiar with, and comfortable with, templating languages such as Handlebars, Dust or Mustache so why was Marko introduced?

What makes Marko different is that it is an HTML-based templating language that allows javascript expressions as attribute values. Any HTML file is a valid Marko template. Because Marko understands the HTML structure of the templates, it can support powerful functionality that would not be possible in text-based templating languages such as Handlerbars, Dust or Mustache. Marko allows developers to extend the HTML language by introducing custom HTML elements and attributes. On top of that, utilizing the HTML structure for applying templating directives makes templates more readable and allows data templates to more closely resemble the final HTML structure.

Let's compare Marko with Handlebars (a text-based templating language):

Handlebars:

<h2>Hello {{name}}!</h2>
 
{{#if colors}}
<ul>
    {{#each colors}}
    <li class="color">
        {{this}}
    </li>
    {{/each}}
</ul>
{{else}}
<div>
    No colors!
</div>
{{/if}}

Marko:

<h2>Hello ${data.name}!</h2>
<ul if(data.colors.length)>
    <li class="color" for(color in data.colors)>
        ${color}
    </li>
</ul>
<div else>
    No colors!
</div>

A few things to note for the Marko template:

Beyond Marko being an HTML-based templating language, it was also designed with extreme performance and extensibility in mind. The Marko compiler gives developers full control over how templates are compiled to JavaScript and the runtime was designed to be as efficient as possible. Marko fully embraces the JavaScript language for better performance and flexibility (e.g. favoring JavaScript expressions over a custom expression language).

Finally, another distinguishing feature of Marko is that it supports asynchronous template rendering. This powerful feature allows portions of the template to be rendered asynchronously. Instead of waiting for all data to come back from remote services before beginning to render the template, you can now immediately start rendering the template and the portions of the template that depend on asynchronous data will render as soon as the asynchronous data becomes available. The Marko rendering engine ensures that the final HTML will be streamed out in the correct order.

Design Philosophy