Template Language That Works on Both Server and Client

Template language that works on both server and client

Try Mustache. (Twitter used it in their recent redesign, so they can share templates between server-side Ruby and client-side JavaScript.)

It's also available in Ruby, JavaScript, Python, Erlang, PHP, Perl, Objective-C, Java, .NET, Android, C++, Go, Lua, ooc, ActionScript, ColdFusion, Scala, Clojure, Fantom, CoffeeScript, D, and for node.js.

(Yes, I know you mentioned it in your question, but this answer has links and stuff.)

Templating language for both client-side and server-side rendering

We ended up picking dust.js. Check out Leaving JSPs in the dust and The client-side templating throwdown for more info.

Templating language for both Ruby and client-side JS

Mustache.

It is Ruby based but there are several different implementations, including JS.

Client-side templating language with java compiler as well (DRY templating)

I'm going for Mustache for now and anticipating a java implementation for Handlebars.js.
Once that exists, the refactoring-path shouldn't be that steep.

EDIT - april 2012

Ok, updating this for future reference:

  • I'm outsourcing server-side templating to Node.js.
  • communication between java and node.js implemented using sockets. (see: Sending data from node.js to Java using sockets for where I got the idea)
  • Since now I only need a client-lib (or better one that runs in javascript on both client and server-side using node) I can choose more freely. Having become accustomed to Mustache, I've chosen the Hogan parser (by the Twitter guys) ( http://twitter.github.com/hogan.js/ )

100% DRY (even the client-side mixins and i18N-bundles come from the same source.
Moreover, Hogan can precompile the templates server-side and open a connection to the client so the client doesn't have to parse the template anymore on first connect.

Is it fast? Lightning...

HTML template filled in server-side and updated client-side

If you would really like to have an initial value stored in an area before Angular activates- you can use the ng-bind attribute rather than {{bound strings}}, from your example:

<ul>
<li ng-repeat="feature in features">
<div ng-bind="feature.title">Hello</div>
<p ng-bind="feature.description">This feature was rendered server-side but can be updated once angular activates</p>
</li>
</ul>

I'm not sure where this would come in handy, but you'll also want to include the initial data-set as part of a script tag in the document, so that when angular DOES activate it doesn't wipe out the displayed information with nulls.

Edit: (As requested by commenters)

Alternatively, you could make an ng-repeat at the top of the list, have it configured to fill out based on the 'features' list itself. Following that ng-repeat element, have non-ng-repeat elements which have an ng-hide attribute with the setting ng-hide="features", if Angular loads, all the elements from the original server-provided list hide themselves, and the angular list jumps into existence. No hacky modifications to Angular, and no fiddling with the direct ng-bind attribute.

As a side note, you might still want to send a piece of script capable of reading that initial server-element for its data to feed it into angular before angular synchronizes if you want to avoid a blink where angular clears the data while waiting for a request for the same data from the server.

Which templating engine can I use with both JS and PHP?

If you like JS->PHP priority :) then you have this two jquery-tmpl compatible template renderer for PHP backend

  1. https://github.com/abackstrom/jquery-tmpl-php
  2. https://github.com/xyu/jquery-tmpl-php

If you prefer more PHP->JS priority :) then you can try this Javascript implementation of popular PHP templating Smarty

  1. http://code.google.com/p/jsmart/

Or you can try something more neutral like:

  1. Mustache http://mustache.github.com/

ASP.NET MVC templates for both client and server

I would oppose rendering server-side and then sending it back to your JS-script for bandwith and performance. Rather you should use a templating engine that works on both the server and the client. When the client wants to refresh the comments, it requests only the data for the comments and then replaces the old comments html with the new html rendered from the data using the same template that is being used on the server.

I've been using Mustache templating engine to achieve this using PHP and JS. There is a .NET version which I guess works for ASP.NET, and I'm guessing you're using ASP.NET.

So what I do is I make sure I have data formatted in the same way in PHP and JS and then render using a Mustache template.

http://mustache.github.com/

Mustache is simple to use. You take one object and one template and you get the HTML back.

Example object:

object->user = "Kilroy"
object->comment = "was here"
object->edited = true

Example template:

{{user}} {{comment}} {{#edited}}(This comment has been edited){{//edited}}

Result:

Kilroy was here (This commment has been edited)

Client side + Server side templating, feels wrong to me, how to optimize?

That's very easy to use Client side + Server side templating.When we are building some web apps,we should use ajax to get some data and use the callback function to deal with it.So we should render these data on the client side.

The question is how to render them on client side?

Now We just need a client side jade.js.

Follow this document : https://github.com/visionmedia/jade#readme

First

git clone https://github.com/visionmedia/jade.git

Second

$ make jade.js ( in fact the project has already compile the file for us )

so we just need to copy this file to the path that we use.

Third

read my demo below :

<script type='text/javascript' language='javascript' src="lib/jquery-1.8.2.min.js"></script>
<script type='text/javascript' language='javascript' src="lib/jade/jade.js"></script>
<script type='template' id='test'>
ul
li hello world
li #{item}
li #{item}
li #{item}
</script>
<script>
var compileText = $("#test").text();
console.log( typeof( compileText ) );
var fn = jade.compile( compileText , { layout : false } );
var out = fn( {item : "this is item " } );
console.log( out );
$("body").append( out );
</script>

Now you can see the output result in the body

hello world
this is item
this is item
this is item

After reading this demo I think that you would know how to seperate jade server side and client side.If you can understand which one compile the jade template,then all the questions are easy.

Maybe you would have another question now.How to write some jade template codes in *.jade?The document also provide us a way to do it.This Tutorial may help you.

index.jade

!!!5
html
head
title hello world
body
ul#list

script#list-template(type='template')
|- for( var i in data )
| li(class='list') \#{ data[i].name }
|- }

index.js

/* you javascript code */
var compileText = $('#list-template').text();
var compile = jade.compile( compileText , { layout : false } );

var data = [{ "name" : "Ben" } , {"name" : "Jack" } , {"name" : "Rose" }];
var outputText = compile( data );

$("#list").append( outputText );

Client-side vs. server-side templating (which one?)

UPD: do it only if you really need it

(4 years and 2 isomorphic enterprise apps later)

If you're required to do SSR, fine. If you can go with a simple SPA - go with it.

Why so? SPAs are easier to develop, easier to debug and cheaper and easier to run.

The development and debugging complications are evident. What do I mean by "cheaper and easier to run", though? Well, guess what, if 10K users try to open your app at the same time your static HTML website (i.e. a built SPA) you won't even feel it. If you're running an isomorphic webapp though, the TTFB will go up, RAM usage will go up and eventually you'll have to run a cluster of those.

So, unless you are required to show some super-low TTFB times (which will likely come through aggressive caching), don't overcomplicate your life.

Original answer from 2015:

Basically you're looking for an isomorphic web app that shares the same code for frontend and backend.

Isomorphic JavaScript

JavaScript applications which run both client-side and server-side. Isomorphic JavaScript frameworks are the next step in the evolution of JavaScript frameworks. These new libraries and frameworks are solving the problems associated with traditional JavaScript frameworks.

I bet this guy explains that much better that me.

Sample Image

So, when a user comes to the page, the server renders the full page with contents. So it loads faster and requires no extra ajax requests to load data, etc. Then, when a user navigates to another page, the usual techniques for single page applications are used.

So, WHY WOULD I CARE?

  • Old browsers / Weak devices / Disabled Javascript
  • SEO
  • Some page load improvements

Old browsers / Weak devices / Disabled Javascript

For example, IE9 does not support History API. So, for old browsers (and if user disables javascript too), they would just navigate through pages just like they did it it in good old days.

SEO

Google says it supports SPA's but SPA's aren't likely to appear in the top results of google search, are they?

Page speed

As it was stated, the first page loads with one HTTP request, and that's all.

OK, so

There are lots of articles on that:

  • http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/
  • http://www.sitepoint.com/isomorphic-javascript-applications/
  • https://www.lullabot.com/articles/what-is-an-isomorphic-application

But SHOULD I CARE?

It's up to you, of course.

Yeah, that's cool, but it takes much work to rewrite/adapt the existing app. And if your backend is in PHP/Ruby/Python/Java/Whatever, I've got bad news for you (it's not necessarily impossible, but close to that).

It depends on the website, you can try to collect some stats and if the percentage of users with old devices is small, it's not worth the trouble, so why not...

LET THEM SUFFER

If you care only about users with old devices, then c'mon, it 2015, and it's your user's problem if he's using IE8 of browsing websites with a iPod Touch 2. For example, Angular dropped IE8 support in 1.3 approximately a year ago, so why wouldn't you just alert the users that they need to upgrade ;)

Cheers!



Related Topics



Leave a reply



Submit