My NYC CodeCamp Talks – Javascript and Node.js

Yesterday I did a couple of talks at the NYC CodeCamp which Lab49 was sponsoring. It was a great event and I really enjoyed meeting many of the 400 developers who attended. My one regret was that due to presenting myself I missed great talks from my fellow Lab49’s Scott Weinstein and Doug Finke.

My first talk was an introduction to Javascript where I explained that despite JavaScript looking an awful lot like C# and Java, it’s in fact not much like them at all. But don’t panic – it’s an extremely simple language and once you understand it’s basics (prototype based inheritance, hoisting, functions, etc..), you’ll be able to understand most JavaScript code out there.

My second talk was an introduction to node.js and how running JavaScript on the server is in fact far from the worst idea. The intention of the talk was not to try to convert a room full of ASP.NET developers to Node, but to explain where node is innovating in the web platform space and how we’ll probably see a lot more of these techniques in the future on every platform (code sharing between client & server, simple API’s for real-time web communication). The demo’s I did during the talk can be found on GitHub.

I’d be really happy to give these talks again so please get in touch with me if you’d be interested in having me speak at any development groups.

Advertisements

Using NodeJs to render JavaScript charts on the server

Ideally, you want both rich interactive charts in your front-end (“just like Google Finance” is a common request) and the ability to render the same charts on the server for exporting, emailing, or supporting less capable clients (Blackberry, I’m looking at you). The perfect scenario would be to do this using the same library so that they look identical, and so you don’t have to maintain two separate code bases. Unfortunately due to limitations in libraries, platforms and environments – it’s difficult to make this a reality.

Recently, I’ve been developing a HTML5 application in which we used the Highcharts charting library to provide basic line and bar charts. Highcharts is a JavaScript library that will render either SVG or VML dependent on the hosting browser (if you’re interested, take a look at some of their demos). To support exports, the library will create an SVG in the browser and post it up to the web server. In the box (figuratively), they supply a php script which will render this content into an image or a PDF then return it over HTTP. This works great for situations where we have a full web browser, but sadly, we have to resort to another charting library that can produce static images to produce images on the server. It’s challenging to get the charts looking identical, and maintaining two code bases is a pain.

Unless you’ve had something better to do than constantly follow blogs and twitter (oh, just me then…), you’ve probably heard about Nodejs. It’s a server-side JavaScript implementation running on top of Google’s excellent V8 engine (the one under Chrome). Using the jsdom library, we can provide an environment similar to a browser into which we can load client-side scripts. With very little work, I was able to load up the Highcharts library in node, then using identical code which I would write for a browser, render the chart and grab the SVG content. Compare a chart rendering in a browser to the following from my node sample:

var $ = window.jQuery,
 Highcharts = window.Highcharts,
 document = window.document,
 $container = $('<div id="container" />'),
 chart;

$container.appendTo(document.body);

chart = new Highcharts.Chart({
 chart: {
  defaultSeriesType: chartType,
  renderTo: $container[0],
  renderer: 'SVG',
  width: width,
  height: height
 },
 series: [{
  animation: false,
  data: data
 }]
});

svg = $container.children().html();

Once we’ve grabbed this SVG content, we can render it to an image using the command line tool convert. As it’s super easy in Node to create a basic web server (literally just a single function), I created a basic server which accepts requests like /bar?data=1,2,3,4 and will return the chart rendered as an image using Highcharts.

this.server = http.createServer(function(request, response) {
	var url = parse(request.url, true),
		chartTypeMatch = /^\/(\w+)$/.exec(url.pathname),
		chartType	= chartTypeMatch ? chartTypeMatch[1] : null,

	/* Some code omitted */
	createHighchartsWindow(function(window) {
		/* chart generation from above */

		svg = $container.children().html();

		// Start convert reading in an svg and outputting a png
		convert	= spawn('convert', ['svg:-', 'png:-']);

		// We're writing an image, hopefully...
		response.writeHeader(200, {'Content-Type': 'image/png'});

		// Pump in the svg content
		convert.stdin.write(svg);
		convert.stdin.end();

		// Write the output of convert straight to the response
		convert.stdout.on('data', function(data) {
			response.write(data);
		});

		// When we're done rendering, we're done
		convert.on('exit', function(code) {
			response.end();
		});
	});
}).listen(2308); // Start HTTP server listening on port 2308

So far I’ve only prototyped these ideas, but it’s working pretty well (see image below). Although I’ve used Highcharts for this example, it should be possible to use any SVG based JavaScript charting package. I feel this technique has the potential to be able to support both rich client side charts and static server generated images using the same libraries, and most importantly, sharing the same code. My prototype is available at up at GitHub. What do you think?

Highcharts chart rendered on Node