Express/Node.js : Render custom javascript as response
Asked Answered
B

3

6

In my application, I need to provide an API (something like the Google Maps javascript API), through which I can send some custom javascript (with some session and request related information) as the response. The javascript is then used to plot some graphs on the UI. I'm using Express with Jade as my templating engine. The code that I'm currently using is:

app.use('/graph',function(req, res){
   //send out graph data
   var var_name = req.session.var_name //fetch something from session
   var graphData = fetchGraphData(req.query.graph); //function that fetches graph data
   res.contentType("text/javascript");
   res.render(__dirname + '/views/graph.jade', {
     title: "Title", queryStr: JSON.stringify({var_name: var_name, graphData: graphData  })
   });
});

And the jade file:

|  some_var_name = {
|       initGraph : function(divId){
|       //some code here
|       var graphData = !{graphData}
|       // do something                               

As a workaround, I have started each line of the jade file with |, so that jade parses the text as plain text, and doesn't add any html tags! It works fine, but is there a cleaner way to do this? The solution may or may not use Jade!

Bougie answered 6/5, 2013 at 22:49 Comment(2)
I don't how much template is actually required, but you can still use res.send to send out any string you want.Wyoming
@Wyoming : Thanks for your response! But I would like to organize the response data in files, as there would be quite a lot of such actions, and the file is quite long too!Bougie
J
6

You should look into underscore templates. I think that for generating arbitrary text output it would be somewhat cleaner. Jade is purpose-built for rendering HTML.

You could also try Mustache or Handlebars.

Based on your comment, I see you'd like to keep using res.render for rendering the template. consolodate.js adds support for all major template engines to Express. Including Underscore templates, Handlebars, Mustache and Dust, mentioned by @TheHippo.

Jewess answered 6/5, 2013 at 23:1 Comment(2)
Also dust should be work fine, as it is language agnostic. (Not only HTML templating)Wyoming
Thanks for your inputs. I went with handlebars. Look much cleaner now!Bougie
F
1

You may try to define JavaScript functions you need to send to the browser in a separate module, outside of the template, which is probably more correct way from the "concerns separation" point of view. Also if functions are defined in a separate module they can be used both in the server and in the browser.

Then you can convert the functions to strings using its toString() method either in a function that invokes the template or right inside the template, if it supports plain JavaScript which is the case with underscore, EJS and doT templates (I tried both underscore and EJS and ended up using doT which is not only the fastest but very versatile - check it out):

JS code:

// if you send the same functions you may want to convert them to strings in advance
var data = {
    funcStr: func.toString();
};
res.render(view, data);

Template (doT):

<script type="text/javascript">
    func = {{= it.funcStr }};

    // now you can call it here if you want but I would use 
    // separate JavaScript files
    func();
</script>

I use it to send pre-compliled templates to the browser together with the page on the first page load, but I think it can be used in your case too.

As a side question, why can't you just bundle all these functions in a separate JavaScript module and load them as normal script file?

Fifine answered 7/5, 2013 at 19:11 Comment(1)
The API that I'm exposing just returns a javascript file after some basic HTTP auth, and the js response contains some auth info and some request parameters for interacting with socket.io. The js response is similar to the google maps API. The response can only be 1 js file, so I can't bundle the functions in a separate file, unless all the separate files are compiled into one before rendering the response!Bougie
V
1

You can use https://www.npmjs.com/package/rendercustomjs package, it works fine but in ejs templating

Vowell answered 27/10, 2021 at 9:6 Comment(1)
You are still editing to complete that sentence, aren't you? Also please do not only name a package/lib. Demonstrate how it solves the problem.Rinderpest

© 2022 - 2024 — McMap. All rights reserved.