Blaze Meets Clusterize.js

Hey all,

On a recent project, I needed to render a very large amount of data on the client. Unfortunately, when it comes to rendering lots of templates, Blaze is slow. After lots of time profiling, debugging, and reading half-finished blog posts, I came to the conclusion that blaze just isn’t suited to rendering a very large number of templates.

So instead of using Blaze directly, I decided to let Clusterize.js manage the heavy lifting of render management. I wrote a blog post describing the process of incorporating Clusterize into a Blaze-based application. It also touches on dealing with client-side caching and maintaining dynamic UI updates.

Hopefully this helps some people out there.

As a note for future work, @loren mentioned forking Clusterize and adding native support for Blaze nodes to preserve reactivity in a more sane way. This would be an awesome improvement, and anyone doing this kind of work in the future should consider looking into it!

7 Likes

Great post!

I don’t think the Clusterize change doesn’t need to be Blaze-specific, just allow nodes (document.createElement) to be passed instead of strings. Currently it works like this:

var strings = ['<tr>…</tr>', '<tr>…</tr>', …];
var clusterize = new Clusterize({
  rows: strings
})

And then to preserve reactivity, instead of giving it nonreactive strings (Blaze.toHTMLWithData), give it:

row1 = document.createElement 'tr'
template = Blaze._TemplateWith data, -> Template.row_contents

// render into the row1 node
Blaze.render template, row1

clusterize = new Clusterize({
  rows: [row1, ...]
})

For more info, see “Off-DOM rendering” section of https://medium.com/parlay-engineering/fixing-your-meteor-app-s-render-performance-a727e918511c#.l8be036zy

3 Likes

That is a very interesting post. I did find one small typo when you invalidate the cache. You probably meant TemplateCache.set?

let rows = data.cursor.fetch().map(function(document) {
  // Has this card already been rendered?
  let html = TemplateCache.get(document._id);
  if (html) {
    return html;
  }

  // Render the card and save it to the cache...
  html = Blaze.toHTMLWithData(template, document);
  TemplateCache.get(document._id, html); // <------- should be .set
  return html;
});

Whoops, good catch. Thanks & fixed!