A "hybrid" approach to server-side compiling/rendering

382 views
Skip to first unread message

jordanbr...@gmail.com

unread,
Jan 8, 2014, 6:13:47 PM1/8/14
to mustac...@googlegroups.com
There are many approaches to doing mustache:
  • send everything to the client and let mustache.js do ALL the work (compile, render, then add to DOM) <---- the worst! 
  • compile the templates on the server then send it to the client to finally get rendered and put in the DOM
  • compile and render everything on the server and send finished HTML to the client (the traditional way)
  • a combination: compile and render most of the templates, then for some templates/partials only compile and let the client work with those when and if they're needed
It's that last "hybrid" approach that I don't know how to do. I've played with several Java mustache implementations and they can do the first three, but I have yet to see how the fourth bullet is done. Please tell me that's easily done with Mustache.java!

thanks

Sam Pullara

unread,
Jan 8, 2014, 6:18:52 PM1/8/14
to mustac...@googlegroups.com
You need to pair it with a client side framework like hogan.js if you want to do that. Sadly because it crosses the language (and network) divide, there isn’t much we can do directly from mustache.java. However, Twitter doesn’t do this specifically because you have to transfer over so much code for very little benefit. Instead all their API calls that would mutate a component also re-render that component in the returned JSON and it is splatted back into the DOM.

Do you have a particular use case in mind? Happy to brainstorm with you.

Sam

--
You received this message because you are subscribed to the Google Groups "mustache.java" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mustachejava...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Josh Unger

unread,
Jan 8, 2014, 7:31:19 PM1/8/14
to mustac...@googlegroups.com
We just started using Mustache.java too and were curious about the same.

How do you handle mapping isEmpty to length and other minor differences?

-josh

Sam Pullara

unread,
Jan 8, 2014, 7:40:53 PM1/8/14
to mustac...@googlegroups.com
All of the references in Twitter’s mustache templates are mapped to a semantic view method and never to something that happens to be defined in the underlying data objects. This was key to making the transition easy from Javascript (hogan.js) / Ruby (internal impl) to the JVM (mustache.java).

Sam

jordanbr...@gmail.com

unread,
Jan 8, 2014, 8:06:20 PM1/8/14
to mustac...@googlegroups.com
Ok, just want to make sure I follow you: in the cases where the client calls the API, you guys do NOT get JSON back, then render mustache, then update DOM? But instead the client makes an API call and gets back rendered HTML, then just plops that into the DOM - the kind of old, regular way, right?

My approach is that the server fully renders like 80% of the page templates (layout, header, sidebar, footer), with the remaining 20% (just rough numbers here) being "precompiled" (this would be like a template for search results, which can't be rendered because we don't have data because the user hasn't searched yet). So all that goes to the client and then the user searches, AJAX brings back data, mustache.js uses that data to render the precomiled template, in the DOM it goes and we're done.

What benefit does this have? All the speed and simplicity of server-side rendering + get to do client-side rendering when it makes sense + our API calls only bring back data, which can get used and reused across the UI. Bringing back the results as rendered HTML is faster and makes sense in some cases, but getting plain old JSON frees us up to use that data for a bunch of different stuff.

Thoughts?

Sam Pullara

unread,
Jan 8, 2014, 8:25:58 PM1/8/14
to mustac...@googlegroups.com
On Jan 8, 2014, at 5:06 PM, jordanbr...@gmail.com wrote:
Ok, just want to make sure I follow you: in the cases where the client calls the API, you guys do NOT get JSON back, then render mustache, then update DOM? But instead the client makes an API call and gets back rendered HTML, then just plops that into the DOM - the kind of old, regular way, right?

Maybe? I’m not sure that I’ve adequately explained it.

My approach is that the server fully renders like 80% of the page templates (layout, header, sidebar, footer), with the remaining 20% (just rough numbers here) being "precompiled" (this would be like a template for search results, which can't be rendered because we don't have data because the user hasn't searched yet). So all that goes to the client and then the user searches, AJAX brings back data, mustache.js uses that data to render the precomiled template, in the DOM it goes and we're done.

On Twitter, the AJAX call brings back a JSON response with the rendered HTML in the JSON. There doesn’t appear to be any advantage to rendering that on the client when you had to call the server anyway.

What benefit does this have? All the speed and simplicity of server-side rendering + get to do client-side rendering when it makes sense + our API calls only bring back data, which can get used and reused across the UI. Bringing back the results as rendered HTML is faster and makes sense in some cases, but getting plain old JSON frees us up to use that data for a bunch of different stuff.

On Bagcheck (RIP) & Twitter, in some cases we bring back data in addition to the rendered HTML if it is really needed somewhere else in the page. You can see this in any of the JSON responses once you are already on the page. One of the big advantages is that when you hit a page it can be completely rendered on the server without a second call. That drastically reduces time-to-value for a visitor. You’ll note that if you go to this page:


It is rendered server side — the WTF/Trends modules come in later as they aren’t considered core to that pages experience and we can delay doing that work, but if you then search for something else, it does another XHR request and returns not only some data in the JSON but also the rendered search result without the chrome around the HTML.  This is my recommendation for sites vaguely like Twitter. I probably wouldn’t do the same thing for Gmail.

Thoughts?

To me, for most sites, it isn’t worth the additional complexity and generally poorer performance (or at least uneven experience based on client) to render in the browser. The only time I would do that is if I had a truly single page web application rather than something more like Twitter where there is dynamic content but generally don’t run the entire application in the client.

Sam

Josh Unger

unread,
Jan 10, 2014, 2:23:39 PM1/10/14
to mustac...@googlegroups.com
Thanks Sam, can you share a code example on replacing isEmpty?  Do you just have boolean?  Second, is there a setting I can set to error out if a developer uses something on an underlying data object?

-josh

jordanbr...@gmail.com

unread,
Jan 12, 2014, 12:06:47 AM1/12/14
to mustac...@googlegroups.com
Here's what makes the most sense to me:

A request comes in for our search page, we want to send back a fully-rendered mustache template. Good, we can do that. That's super fast!
The search page has a search box with auto-suggest, which makes an XHR call to a third-party for its suggestion data. No problem! That's much better than a page reload.
The suggestion data comes back and we want to render the results using a mustache template. Uh oh! The server already rendered that part of the template, i.e. our 'suggestions' partial!

We have to A) go old school and write some jQuery DOM manipulation, or B) send another request (XHR or full request) to our server with this suggestion data and get back a rendered 'suggestions' template. Neither of those make sense.

A 'C' option of originally getting a rendered template with compiled partials included in the response would be ideal. That way we can use those compiled partials client-side and avoid any additional requests for rendering suggestion results. So basically after the initial page request, which returns a partially-rendered page, the client can then easily re-render parts of the page with data that comes from all kinds of services (back to your own server, third-parties, etc.). This is the ideal hybrid approach that lets front-end engineers do what makes most sense for a given scenario.

What you described is great for a lot of cases, but if you need the client to get data AND render a template you can't (well, without doing really slow template compilation in the browser).

So, how about a 'hybrid' option in Mustache.java?

-Jordan

Sam Pullara

unread,
Jan 12, 2014, 12:14:58 AM1/12/14
to mustac...@googlegroups.com
On Jan 11, 2014, at 9:06 PM, jordanbr...@gmail.com wrote:
Here's what makes the most sense to me:

A request comes in for our search page, we want to send back a fully-rendered mustache template. Good, we can do that. That's super fast!
The search page has a search box with auto-suggest, which makes an XHR call to a third-party for its suggestion data. No problem! That's much better than a page reload.
The suggestion data comes back and we want to render the results using a mustache template. Uh oh! The server already rendered that part of the template, i.e. our 'suggestions' partial!

We have to A) go old school and write some jQuery DOM manipulation, or B) send another request (XHR or full request) to our server with this suggestion data and get back a rendered 'suggestions' template. Neither of those make sense.

Maybe you're misunderstanding me on this point. The response from the suggestion service includes the HTML to splat into the page. There is no second call back to the server. You'd get something like:

{ "results" : [ "sam", "samantha", "sam pullara"], "html":"<ul class='suggestions'><li><b>sam</b></li><li><b>sam</b>antha</li><li><b>sam</b> pullara</li></ul>"  }

Your client side code would have the data if it needed it, but could just grab the html and put it in the page and not have to render anything.

A 'C' option of originally getting a rendered template with compiled partials included in the response would be ideal. That way we can use those compiled partials client-side and avoid any additional requests for rendering suggestion results. So basically after the initial page request, which returns a partially-rendered page, the client can then easily re-render parts of the page with data that comes from all kinds of services (back to your own server, third-parties, etc.). This is the ideal hybrid approach that lets front-end engineers do what makes most sense for a given scenario.

If you are talking to third-parties and you want to render those client side (i suggest proxying through your server) definitely use my suggestion below.

What you described is great for a lot of cases, but if you need the client to get data AND render a template you can't (well, without doing really slow template compilation in the browser).

Hogan.js will precompile templates with "hulk".


So, how about a 'hybrid' option in Mustache.java?

Since this crosses over to compiling to Javascript, I don't think it is obvious what that means. Just compile them with hogan.js during your build and ship them back with the response I guess? Both hogan.js and mustache.java support basically the same templates / features.

Sam

Sam Pullara

unread,
Jan 12, 2014, 12:17:03 AM1/12/14
to mustac...@googlegroups.com
On Jan 10, 2014, at 11:23 AM, Josh Unger <joshu...@gmail.com> wrote:
Thanks Sam, can you share a code example on replacing isEmpty?  Do you just have boolean?  Second, is there a setting I can set to error out if a developer uses something on an underlying data object?

It would really just be something simple. For example your template might be:

{{#noitems}}...{{/noitems}}

With backing code that is like:

boolean noitems() {
  return itemlist.isEmpty();
}

There are a few examples of how to write mustache visitors and object handlers that can do that sort of thing in the tests. I'd probably just make an object handler that verified that classes in your packages are only in a view package.

Sam
Reply all
Reply to author
Forward
0 new messages