Architectural Tips for people still writing UI in Blaze.

When developers first started using MeteorJS, the front-end framework Blaze was all the craze. Blaze helped developers learn a new system by creating a way to build applications quickly. Blaze is a UI abstraction using a version of Handlebars called Spacebars as the Templating language, jQuery for DOM manipulation, and the magical Tracker library for rendering and re-rendering in response to data changes.

Now I love React. I fell in love with it since the great F8 conference and really am excited about the Virtual DOM. Our company is moving towards this because we believe it’s easier to reason about and we can leverage a broader audience of developers who may be out of the Meteor community. Flux the de facto architectural pattern gives you the foundation for building an app as well! The issue is we needed to get organized NOW. We don’t have the luxury of closing shop and building the Frontend all over again. So we decided, let’s get in the right mentality so we could use ANY front end framework and our patterns would still hold true.

None of our code really was a problem, there was just a lot of it. There was just tons of business logic duplicated between files making you scream at your computer for lack of module support. :( It was hard to reason about state changes using Session, subscriptions in the Router causing weirdness in rendering, the list goes on. It was safe to say that the UI plain was a dark and murky place.

Here are some tips for building rich user experiences in Meteor. These points are just general tips and will probably follow us through any view layer.

Don’t abuse Session.

It gets really annoying managing Session variables in UIs that are only confined to a single page, or where the state of this variable doesn’t need to persist. I was once a young Sessioner…I abused it. I actually thought Meteor was going to make it more powerful…then it hit me… Reactive Vars and Reactive Dictionaries, scoped to your template, are way easier to reason about. For product requirements between pages or logic that are based on a user’s Session then it seems like Session variables are a good idea.

Smart Components and Dumb Components.

This is a huge concept in the React landscape. It’s the idea that you should build components purely for data fetching and components purely for display. At Workpop when we first create our pages, we have a Smart Component that subscribes to data via a “Template Level Subscription” and then creates several reactive variables if we need to hold special state. We also have components that call Methods in a templates `onCreated` function to create the state. We then pass this state to our dumb components as a data source to power their display. These smart components are “wrappers” or “containers”, or an example of how a separation of concerns is still a good idea even in database-everywhere environments.

Pass your data context from the top down.

If you wanna save yourself from the great data context rat race, then be very strict about how data flows through your app. It’s easy to get carried away…our concept of local data is a nicely equipped mini-mongo. Getting data from any point is so easy it almost feels wrong NOT to do it. Trust me, those smart components we were talking about? It’s gonna feel good when you know exactly who is responsible for what when you’re examining your UI for bugs. Pass data from the smart components down to the dumb ones. You can either pass data directly into your templates, use their context in markup, or create template helpers based on the template’s data and use those in your markup. See below.

{{> dumbComponent data1=data1 someData=data2 data3=someOtherData }}
<template name="dumbComponent">
{{#if data1}}
{{!-- do some stuff --}}
{{someData}} is {{data3}}
{{/if}}
</template>
OR
Template.dumbComponent.helpers({
'showSomething': function () {
var template = Template.instance();
return template.data.data1;
}
});
<template name="dumbComponent">
{{#if showSomething}}
{{!-- do some stuff --}}
{{/if}}
</template>

Stay away from “this”.

I’ve said it once, and I’ll say it again. In Blaze, it is hard to reason about data context. You can be in different blocks and write code that can easily change based on scope. With Meteor 1.2 there are additions to Spacebars like let scoping. This will help but in JavaScript code…Template.instance() or Blaze.getData() is your best friend. I know that in the lifecycle hooks, onCreated, onRendered, onDestroyed, this, refers to the template instance, just store this reference into a variable and proceed like normal.

//This is how I setup my life cycles. We also order our template files in this exact order.
Template.someTemplate.onCreated(function () {
//in this template, 'this' is the template instance.
var template = this;
// proceed with whatever i'm going to do here
});
Template.someTemplate.helpers({
someHelper() {
var template = Template.instance();
//proceed with whatever
}
});
Template.someTemplate.onRendered(function () {
//in this template, 'this' is the template instance.
var template = this;
// proceed with whatever i'm going to do here
});
Template.someTemplate.events({
'click .some-button': function (event, template){
// use template here directly or if you need the data of an
// iteratee use Blaze.getData(event.currentTarget)
}
});
Template.someTemplate.onDestroyed(function () {
//in this template, 'this' is the template instance.
let template = this;
// proceed with whatever i'm going to do here
});

Stop subscribing in the Router.

This is merely a personal opinion, but with the aid of Template level subscriptions, smart components can be created that can give your app a nice separation of concerns. The Routers job is to render some layout, perform some triggered action. Leave the data management up to your Smart UI Components.

Encapsulate your Components with CSS Selectors.

When you have a large team and can’t pay the cost of keeping up with CSS regressions, you should wrap your components in special classes that act as a container of style. This way you can write scoped CSS and not affect existing legacy code that may exist. Once you recognize patterns between components, you should write some mixins and share CSS. Approach your CSS like you do your javascript and it’ll all feel natural. Components that have to display something need to look their best, so get a styling!

/* So we have someTemplate above. */
/* IN OUR LESS/SCSS/CSS Files */
.some-template {}
/* use a class if its a component that will be repeated */
#some-template {}
/* use an id if its one component *

In Conclusion

I really feel good about where our Blaze architecture is going today, there are still TONS of debt to clean up, but I feel confident that we can build any UI going forward. I’m just afraid that as other UI communities grow, it will make more sense for you to dive into other libraries like React or Angular. Even so, if you are still using Blaze, I think these tips will take you a long way.

Let me know what you think! Respond below! Let’s chat it out!