Overview
Blaze is a powerful library for creating user interfaces by writing reactive HTML templates. Compared to using a combination of traditional templates and jQuery, Blaze eliminates the need for all the “update logic” in your app that listens for data changes and manipulates the DOM. Instead, familiar template directives like {{#if}}
and {{#each}}
integrates with Tracker’s “transparent reactivity” and Minimongo’s database cursors so that the DOM updates automatically.
Quick Start
Blaze is a Meteor-only package for now. Soon we will have Blaze on npm so you can use it in your stack.
Each new Meteor project you create has Blaze included (the blaze-html-templates
package).
Prerequisite
Earlier, jQuery
was bundled with Blaze. In later versions Blaze does not have jQuery
as a direct dependency. With some legacy Blaze packages you might encounter the following error.
1 | Uncaught Error: jQuery not found |
To mitigate this error it is advised to install jQuery
either as an npm
or as a atmospherejs
package.
install jquery with npm
Into project root.
1 | meteor npm install jquery@latest --save |
Import jQuery
in client/main.js
.
1 | import $ from 'jquery'; |
install jquery with atmospherejs
Into project root.
1 | meteor add jquery@3.0.0 |
Import jQuery
in client/main.js
.
1 | import {$} from 'meteor/jquery'; |
Details
Blaze has two major parts:
A template compiler that compiles template files into JavaScript code that runs against the Blaze runtime library. Moreover, Blaze provides a compiler toolchain (think LLVM) that can be used to support arbitrary template syntaxes. The flagship template syntax is Spacebars, a variant of Handlebars, but a community alternative based on Jade is already in use by many apps.
A reactive DOM engine that builds and manages the DOM at runtime, invoked via templates or directly from the app, which features reactively updating regions, lists, and attributes; event delegation; and many callbacks and hooks to aid the app developer.
Blaze is sometimes compared to frameworks like React, Angular, Ember, Polymer, Knockout, and others by virtue of its advanced templating system. What sets Blaze apart is a relentless focus on the developer experience, using templating, transparent reactivity, and interoperability with existing libraries to create a gentle learning curve while enabling you to build world-class apps.
Examples
Here are two Spacebars templates from an example app called “Leaderboard” which displays a sorted list of top players and their scores:
1 | <template name="leaderboard"> |
The template tags and
refer to properties of the data context (the current player), while
players
and selected
refer to helper functions. Helper functions and event handlers are defined in JavaScript:
1 | Template.leaderboard.helpers({ |
No additional UI code is necessary to ensure that the list of players stays up-to-date, or that the “selected” class is added and removed from the LI elements as appropriate when the user clicks on a player.
Thanks to a powerful template language, it doesn’t take much ceremony to write a loop, include another template, or bind an attribute (or part of an attribute). And thanks to Tracker’s transparent reactivity, there’s no ceremony around depending on reactive data sources like the database or Session; it just happens when you read the value, and when the value changes, the DOM will be updated in a fine-grained way.
Principles
Gentle Learning Curve
To get started with Blaze, you don’t have to learn a lot of concepts or terminology. As web developers, we are already students of HTML, CSS, and JavaScript, which are complex technologies described in thick books. Blaze lets you apply your existing knowledge in exciting new ways without having to read another book first.
Many factors go into making Blaze easy to pick up and use, including the other principles below. In general, we prefer APIs that lead to simple and obvious-looking application code, and we recognize that developers have limited time and energy to learn new and unfamiliar terms and syntaxes.
It may sound obvious to “keep it simple” and prioritize the developer experience when creating a system for reactive HTML, but it’s also challenging, and we think it’s not done often enough! We use feedback from the Meteor community to ensure that Blaze’s features stay simple, understandable, and useful.
Transparent Reactivity
Under the hood, Blaze uses the Tracker library to automatically keep track of when to recalculate each template helper. If a helper reads a value from the client-side database, for example, the helper will automatically be recalculated when the value changes.
What this means for the developer is simple. You don’t have to explicitly declare when to update the DOM, or even perform any explicit “data-binding.” You don’t have to know how Tracker works, or even exactly what “reactivity” means, to benefit. The result is less thinking and less typing than other approaches.
Clean Templates
Blaze embraces popular template syntaxes such as Handlebars and Jade which are clean, readable, and familiar to developers coming from other frameworks.
A good template language should clearly distinguish the special “template directives” (often enclosed in curly braces) from the HTML, and it should not obscure the structure of the resulting HTML. These properties make templating an easy concept to learn after static HTML (or alongside it), and make templates easy to read, easy to style with CSS, and easy to relate to the DOM.
In contrast, some newer frameworks try to remake templates as just HTML (Angular, Polymer) or replace them with just JavaScript (React). These approaches tend to obscure either the structure of the template, or what is a real DOM element and what is not, or both. In addition, since templates are generally precompiled anyway as a best practice, it’s really not important that raw template source code be browser-parsable. Meanwhile, the developer experience of reading, writing, and maintaining templates is hugely important.
Plugin Interoperability
Web developers often share snippets of HTML, JavaScript, and CSS, or publish them as libraries, widgets, or jQuery plugins. They want to embed videos, maps, and other third-party content.
Blaze doesn’t assume it owns the whole DOM, and it tries to make as few assumptions as possible about the DOM outside of its updates. It hooks into jQuery’s clean-up routines to prevent memory leaks, and it preserves classes, attributes, and styles added to elements by jQuery or any third-party library.
While it’s certainly possible for Blaze and jQuery to step on each other’s toes if you aren’t careful, there are established patterns for keeping the peace, and Blaze developers rightfully expect to be able to use the various widgets and enhancements cooked up by the broader web community in their apps.
Comparisons to other libraries
Compared to Backbone and other libraries that simply re-render templates, Blaze does much less re-rendering and doesn’t suffer from the dreaded “nested view” problem, which is when two templates can’t be updated independently of each other because one is nested inside the other. In addition, Blaze automatically determines when re-rendering must occur, using Tracker.
Compared to Ember, Blaze offers finer-grained, automatic DOM updates. Because Blaze uses Tracker’s transparent reactivity, you don’t have to perform explicit “data-binding” to get data into your template, or declare the data dependencies of each template helper.
Compared to Angular and Polymer, Blaze has a gentler learning curve, simpler concepts, and nicer template syntax that cleanly separates template directives and HTML. Also, Blaze is targeted at today’s browsers and not designed around a hypothetical “browser of the future.”
Compared to React, Blaze emphasizes HTML templates rather than JavaScript component classes. Templates are more approachable than JavaScript code and easier to read, write, and style with CSS. Instead of using Tracker, React relies on a combination of explicit “setState” calls and data-model diffing in order to achieve efficient rendering.
Future Work
Components
Blaze will get better patterns for creating reusable UI components. Templates already serve as reusable components, to a point. Improvements will focus on:
- Argument-handling
- Local reactive state
- “Methods” that are callable from other components and have side effects, versus the current “helpers” which are called from the template language and are “pure”
- Scoping and the lookup chain
- Inheritance and configuration
Forms
Most applications have a lot of forms, where input fields and other widgets are used to enter data, which must then be validated and turned into database changes. Server-side frameworks like Rails and Django have well-honed patterns for this, but client-side frameworks are typically more lacking, perhaps because they are more estranged from the database.
Meteor developers have already found ways and built packages to deal with forms and validation, but we think there’s a great opportunity to make this part of the core, out-of-the-box Meteor experience.
Mobile and Animation
Blaze will cater to the needs of the mobile web, including enhanced performance and patterns for touch and other mobile interaction.
We’ll also improve the ease with which developers can integrate animated transitions into their apps.
JavaScript Expressions in Templates
We plan to support JavaScript expressions in templates. This will make templates more expressive, and it will further shorten application code by eliminating the need for a certain class of one-line helpers.
The usual argument against allowing JavaScript expressions in a template language is one of “separation of concerns” – separating business logic from presentation, so that the business logic may be better organized, maintained, and tested independently. Meanwhile, even “logicless” template languages often include some concessions in the form of microsyntax for filtering, querying, and transforming data before using it. This special syntax (and its extension mechanisms) must then be learned.
While keeping business logic out of templates is indeed good policy, there is a large class of “presentation logic” that is not really separable from the concerns of templates and HTML, such as the code to calculate styles and classes to apply to HTML elements or to massage data records into a better form for templating purposes. In many cases where this code is short, it may be more convenient or more readable to embed the code in the template, and it’s certainly better than evolving the template syntax in a direction that diverges from JavaScript.
Because templates are already precompiled to JavaScript code, there is nothing fundamentally difficult or inelegant about allowing a large subset of JavaScript to be used within templates (see e.g. the project Ractive.js).
Other Template Enhancements
Source maps for debugging templates. Imagine seeing your template code in the browser’s debugger! Pretty slick.
True lexical scoping.
Better support for pluggable template syntax (e.g. Jade-like templates). There is already a Jade package in use, but we should learn from it and clarify the abstraction boundary that authors of template syntaxes are programming against.
Pluggable Backends (don’t require jQuery)
While Blaze currently requires jQuery, it is architected to run against other “DOM backends” using a common adaptor interface. You should be able to use Zepto, or some very small shim if browser compatibility is not a big deal for your application for some reason. At the moment, no such adaptors besides the jQuery one have been written.
The Blaze team experimented with dropping jQuery and talking directly to “modern browsers,” but it turns out there is about 5-10K of code at the heart of jQuery that you can’t throw out even if you don’t care about old browsers or supporting jQuery’s app-facing API, which is required just to bring browsers up to the modest expectations of web developers.
Better Stand-alone Support
Blaze will get better support for using it outside of Meteor, such as regular stand-alone builds.
Resources
Packages
- blaze
- blaze-tools
- html-tools
- htmljs
- spacebars
- spacebars-compiler