Monday, August 22, 2011

Resources

Node Homepage

http://nodejs.org

Github

https://github.com/joyent/node

Node API documentation (v0.4.11)

http://nodejs.org/docs/v0.4.11/api

Available Modules

https://github.com/joyent/node/wiki/modules

Tutorials

http://howtonode.org/

http://nodetuts.com/tutorials

http://www.nodebeginner.org/

http://www.google.com :)

Saturday, August 20, 2011

Creating A Module

Module


var counter = 0;

exports.counter = function() {
  return counter++;
};

Using the Module


var mymodule = require('./mymodule');

setInterval(function() {
    console.log(mymodule.counter())
  }, 1000);

Friday, August 19, 2011

Building a Simple Web App - Step 5

Install jsdom


npm install jsdom

Install jquery


npm install jquery

Alter Hello World file to do server side magic


var jsdom = require('jsdom');
var jquery = require('jquery');
var express = require('express');

var app = express.createServer();

app.set('view engine', 'jade');

app.configure(function() {
  app.use(express.static(__dirname + '/static'));
});

app.get('/', function(req, res) {
  res.render('index', {title: 'Express/Jade Example'});  
});

app.get('/:dir', function(req, res) {
  var dir = req.params.dir.toLowerCase();
  res.render(dir, {title: dir + ' page'}, function(err, contents){
    var document = jsdom.jsdom(contents);
    var window = document.createWindow();
    var $ = jquery.create(window);

    $('#nav li a').each(function(index) {
      if($(this).text().toLowerCase() == dir) {
    $(this).addClass('current');
      } else {
    $(this).removeClass('current');
      }
    });

    res.send(window.document.innerHTML);

  });
});

app.listen(3000);
console.log('Server is running on localhost:3000');

Building a Simple Web App - Step 4

Add navigation to layout.jade


ul#nav
      li 
        a(href='/', class='current') Home
      li
        a(href='/summary') Summary
      li 
        a(href='/map') Map

Add nav styles to styles.css


#nav {  
  margin: 0;
  padding: 0;
}

#nav li {
  display: inline;
}

#nav a:link,
#nav a:visited {
  color: #000;
  background: #b2b580;
  padding:20px 40px 4px 10px;
  text-decoration: none;
}

#nav a.current {
  color: #fff;
}

Create summary.jade and map.jade in Views folder


Create route for new summary and map pages in express


app.get('/:dir', function(req, res) {
  res.render(req.params.dir, {title: req.params.dir + ' page'});
});

Building a Simple Web App - Step 3

Create A Layout - layout.jade in Views folder


html
  head
  title #{title}
  body    
    !{body}
    div#myDiv Hello from layout

Alter index.jade


h1 Hello World From index.jade

Create static file - styles.css


#myDiv {
  font-size: 18px;
  color: red;
}

Link to css file in layout.jade


link(href='/css/styles.css', rel='stylesheet', type='text/css')

Tell express to serve static files


app.configure(function() {
  app.use(express.static(__dirname + '/static'));
});

Building a Simple Web App - Step 2

Install Jade - View Template Engine


npm install jade

Create index.jade in Views folder


html
  head
  title #{title}
  body
    h1 Hello World

Modify your Hello World file


var express = require('express');

var app = express.createServer();

app.get('/', function(req, res) {
  res.render('index.jade', {layout: false, title: 'Express/Jade Example'});  
});

app.listen(3000);
console.log('Server is running on localhost:3000');

Building a Simple Web App - Step 1

Install Express


npm install express

Create Hello World Server


var express = require('express');

var app = express.createServer();

app.get('/', function(req, res) {
    res.send('Hello World!');
});

app.listen(3000);
console.log('Server running on localhost:3000');

Saturday, August 6, 2011

Debugging

Debugging with node-inspector


  1. Install node-inspector

    npm install -g node-inspector
    
  2. Enable debugging on the program you want to debug:


    node --debug HelloWorldServer.js
    

  3. Launch node inspector:


    node-inspector &
    

  4. Open a WebKit browser ie. Chrome to http://127.0.0.1:8080/debug?port=5858
  5. Click on the Scripts tab and choose your js file from the list
  6. Happy Stepping Over, Stepping Into, Stepping Out!

Friday, August 5, 2011

Chat Web Server

This application will use a new module found on https://github.com/joyent/node/wiki/modules.
npm install faye

The faye module is built on the bayeux protocol and passes messages to all connected clients. The server code will handle two endpoints - the faye endpoint on port 8000 and a web server on port 9000 to server up the user's page.

application.js:
var express = require('express');
var faye = require('faye');

// Create the faye server
var bayeux = new faye.NodeAdapter({mount: '/faye', timeout: 45});
bayeux.listen(8000);

// Create the web server
var server = express.createServer();
server.configure(function() {
server.use(express.static(__dirname + '/public'));
});
server.listen(9000);

console.log('Web Server listening on 9000, Bayeux on 8000');

The html page has a simple form to allow the user to input a message and some javascript to hook up the events and publish the messages.

public/index.html:
<html>
<head>
<script type="text/javascript" src="http://localhost:8000/faye.js"></script>
</head>
<body>

<div style="width:800px; margin:5px; padding:5px;">
<input id="message" type="text" size="70"></input>
<input id="post" type="submit" value="Post Message"></input>
<ul id="messages" style="border:1px solid Silver; padding:5px 0;"></ul>
</div>

<script type="text/javascript">

// Create a "unique" id for this client (hack)
var id = Math.floor(Math.random() * 100000);

// Create the client and connect to the server
var client = new Faye.Client('http://localhost:8000/faye');
client.connect();

// Subscribe to the chat channel to receive messages
client.subscribe('/faye/chat', function(message) {
var messages = document.getElementById('messages');
messages.innerHTML = '<li style="margin-left:20px;">' +
message.text + '</li>' + messages.innerHTML;
});

// Handle the button click to allow users to post messages
var button = document.getElementById('post');
button.onclick = function() {
var message = document.getElementById('message');
if (message.value != '') {
client.publish('/faye/chat', { text: id + ': ' +
message.value })
message.value = '';
message.focus();
}
return false;
}

</script>

</body>
</html>

A huge advantage of node is the ability to share code between applications in the browser and applications in the server. Let's add a server "bot" that will respond to chat messages. We do this with the same code the browser does:
// Create a client on the server
// Code is nearly identical to browser
bayeux.getClient().subscribe('/faye/chat', function(message) {
if (message.text.indexOf('admin:pid') > -1) {
bayeux.getClient().publish('/faye/chat',
{ text:'admin pid is ' + process.pid }
);
}
});

Chat Server

var net = require('net');
var sockets = [];
net.createServer(function(socket) {
sockets.push(socket);

socket.on('data', function(data) {
console.log(socket.remoteAddress + ' - ' + data);
for(var i = 0; i &lt; sockets.length; i++) {
if (sockets[i] != socket)
sockets[i].write(data);
}
});

socket.on('end', function() {
sockets.splice(sockets.indexOf(socket), 1);
})

}).listen(9000, 'localhost');


What's going on here?
  • Line 2 creates an array for us to store a reference to the sockets
  • Line 3 creates the socket server where we pass in our callback function
  • Line 4 adds the new socket to our array
  • Lines 5-11 writes the incoming data to each socket in our listen
  • Lines 12-14 removes any dead sockets - why can we do this without locking?

Thursday, August 4, 2011

Hello World - Web Server

var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World');
});
server.listen(4567);
console.log('Server is running at http://localhost:4567');

Lets take this example a bit further and add a setTimeout function to simulate a long running database query. Now each web request will take 1 second to complete.

var http = require('http');
var server = http.createServer(function(request, response) {
response.writeHead(200, {'Content-Type':'text/plain'});
setTimeout(function() {
response.end('Hello World');
}, 1000);
});
server.listen(4567);
console.log('Server is running at http://locahost:4567');

Start the server and run apache bench against it. How long do the following take to finish?

ab -n 10 -c 1 http://localhost:4567/ (1 user sending 10 requests)

ab -n 100 -c 10 http://localhost:4567/ (10 users sending 10 requests)

ab -n 1000 -c 100 http://localhost:4567/ (100 users sending 10 requests)

How would would you do this in Ruby/Python/.Net/Java? Would you get similar response times?

Wednesday, August 3, 2011

Hello World!

  1. Type the following into a file called HelloWorld.js


    setTimeout(
      function() { 
        console.log('World'); 
      }, 2000);
    
    console.log('Hello');
    

  2. Launch your program in Node and watch in amazement:


    node HelloWorld.js
    

Tuesday, August 2, 2011

Installing Node

Official wiki

Installation Guide


Installing on Ubuntu/Linux


#prerequisites on ubuntu

sudo apt-get install git

sudo apt-get install libssl-dev

#download node and build

sudo git clone http://github.com/joyent/node.git

cd node

sudo git checkout v0.4.10

sudo ./configure

sudo make

sudo make install

#check if it worked
node -v

Install on Windows

Don't!

A Windows pre-built binary has been released but it is unstable. You can download it here: http://nodejs.org/dist/v0.5.4/node.exe

We would suggest running a Linux VM to play around with node.


NPM - Node Package Manager

Unix install

curl http://npmjs.org/install.sh | sh


Or

sudo git clone http://github.com/isaacs/npm.git

cd npm

sudo make install


Did it work?


node -v

npm -v

Monday, August 1, 2011

What Is Node.js?

History

  1. Official name is "Node". Unofficial name is "Node.js"
  2. Written by Ryan Dahl in 2009
  3. Dahl is employed by Joyent, Node's main sponsor (http://github.com/joyent/node)

What is it?

  1. server-side JavaScript environment
  2. runs on top of Google's V8 JavaScript engine (engine in Chrome)
  3. event-driven I/O - not just web servers, but also things like sockets

Why is it useful?

  1. it's javascript!
  2. on the server!
  3. less resource requirement on the server - does not spawn a new thread for every request. Instead, it allocates resources as needed.
  4. does not directly block for I/O calls

Who's using it?

  1. Yammer
  2. Github
  3. 37Signals
  4. Palm/HP (webOs)
  5. Rdio
  6. https://github.com/joyent/node/wiki/Projects,-Applications,-and-Companies-Using-Node