brikis98 / node-backbone-skeleton

A skeleton project for creating applications that use node.js server-side, backbone.js client-side, underscore.js templates, CoffeeScript as a JS pre-processor and Compass/SASS as a CSS pre-processor..
84 stars 16 forks source link

Jade => JST (or .html) #1

Closed ghost closed 13 years ago

ghost commented 13 years ago

I like the basic skeleton here a lot. Completely new to node, coming over from Rails, and I'm still trying to get my head around it all, though it looks fairly straightforward.

I was just wondering about the view templating though. I'd love to write view templates in Jade or EJS and preprocess them in development to output a JST template for underscore to then fill in the variable values (sort of like we're doing with coffeescript on the application code). I'll play around with it more tonight and see if I can make it work, but I was wondering if you might have already tried the same, so cut down on the time to write templates? I realize it

Either way, thanks for the skeleton. It's a good starting point for digging into the express framework and beyond.

brikis98 commented 13 years ago

It should be fairly straightforward to swap out the underscore templates for EJS or Jade. Right now, files marked as templates (.html files under templates, by default) are compiled into .js files using underscore in the util/watcher class. If you compile them using EJS or Jade's code instead, you should be more or less good to go. I've done this for dust before (http://akdubya.github.com/dustjs/) and it's not too tough.

If I have some time, I'll make the template engine a bit more "modular" so you can swap it out with ease.

ghost commented 13 years ago

Would it be possible to go from jade to a template for underscore though? I tend to think of Jade -> html, when really what I want is jade -> template to be used by underscore so that it can be used both server-side and client-side, sending a full html page when .html is requested, but just feeding the client .json when possible.

Could we feed it through Jade, for example, but leave <%= variables %> in place to be swapped out by underscore, either on the server or on the client, depending on the request type.

1.) all templates processed from Jade to javascript templates 2.) javascript templates processed into html by underscore

Then in the application [pseudo code]

if request is .html then send _template(template.jst, response_data) [thus sending .html] else send response_data [thus sending json, which underscore will process on the client side]

Again, I'm new to node.js, so I appreciate your input. It's probably simpler than I'm making it out to be.

Cheers

brikis98 commented 13 years ago

Jade and EJS are templating languages. You don't need to pass them through underscore if you've got the Jade/EJS code already. The file extension on templates is irrelevant; I use .html because most editors understand it and it's easy to check the HTML structure by just opening it up in a browser. Feel free to use .tmpl, .ejs, .jade, or anything else instead.

Once the template is written, you run it through the corresponding template library (dust, EJS, jade, etc) to convert it into a JavaScript file (.js). So index.html gets compiled to index.js with a function index(context) inside of it. node-backbone-skeleton does this automatically every time you hit save. You can then include this file in the browser (automatically done by node-backbone-skeleton) and anywhere in the JS code call index({foo: 'bar'}) to render it. node-backbone-skeleton also includes it in an object called templates in server.js so you can use the same template for rendering server side.

ghost commented 13 years ago

Ah, so the resultant JS template is the same regardless of the templating language used? If I use Jade server-side to create the templates I can still use Underscore's _template function to parse in the variables on the client-side when sending JSON? I was just wondering because I remember seeing some benchmarks somewhere slowing how show Jade was, etc. But if that is only referring to the initial (pre)compile, then it's fairly irrelevant, and I'd like to explore the convenience during development. Thanks again mate, I appreciate your patience in setting me straight.

brikis98 commented 13 years ago

No, they are not all the same. The thing you need to understand is that each of the templating libraries (dust, jade, etc) takes some sort of templating syntax and compiles it into JavaScript code. The template syntax is different for each one, so you have to use the corresponding library to compile it; consequently, the resulting JavaScript code for each templating library will be different as well. So if you're using Jade, you use Jade throughout, not underscore. However, since it's JavaScript, you can run it in the browser and in Node.js to render the same template client or server side.

What I do in node-backbone-skeleton is merely save the "resulting JavaScript code" after compilation into a .js file (for the browser) and store it in a "templates" object in node.js. This effectively caches it so you don't have to compile the template before rendering each time.

For example, with Jade, you compile a template written in Jade's syntax like so: var fn = jade.compile('template in jade syntax');. The result of this compilation is a JavaScript function. If I call it on some JSON data, fn.call(scope, locals);, I get a rendered template (HTML) back. node-backbone-skeleton does the compilation step for you automatically every time you change a template file and stores the generated function in a file and in the templates object. So if the template was named index.html, you'd be able to then all templates['index'].call(scope, locals).

As far as performance goes, you need to consider a few things:

  1. Did the performance tests include the time it took to compile the template or only the rendering?
  2. How realistic is the thing being rendered? If it consists of 50,000 HTML elements, is that really a use-case that reflects a real page?
  3. How big, exactly, is the difference? Most of what I've seen amounts to a few ms on a real-world page. It's completely unnoticeable to the user, so you're better of picking the language based on what syntax/features you like best instead of performance.
ghost commented 13 years ago

So we have source template ->(compiling)-> Javascript code -> (compiling with locals) -> HTML

Performance aside (the benchmarks looked good, but I agree with you that it's minimally important in reality), the goal is to use jade for the first compiling stage, but underscore for the second. Even if performance is similar, we're already including underscore client side in order to support backbone, so I want to take advantage of that and not add more overhead. I'm surprised this approach isn't fairly common, as it would let us develop server side with whatever templating language is most convenient, without adding another library that has to be piped down to the client.

I haven't yet had a chance to see the javascript output of the first compiling stage in jade (EJS might be better since it's already extremely similar to the underscore template syntax), but I imagine that it shouldn't be too difficult. It might involve escaping the compilation of locals that we pre-code in underscore syntax, or setting the underscore syntax to fill in locals using a syntax that fits the jade stage 1 compiling output.

For developers preparing the second compilation stage is always effortless (feed in some locals, done), whereas the first is laborious (code all the semantic html with embedded js). So it makes sense that want the most usable templating language for the first, but the most efficient one for the second (especially if it's happening client-side).