Monday, August 22, 2011
Resources
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
- Install node-inspector
npm install -g node-inspector
- Enable debugging on the program you want to debug:
node --debug HelloWorldServer.js
- Launch node inspector:
node-inspector &
- Open a WebKit browser ie. Chrome to http://127.0.0.1:8080/debug?port=5858
- Click on the Scripts tab and choose your js file from the list
- Happy Stepping Over, Stepping Into, Stepping Out!
Friday, August 5, 2011
Chat Web Server
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 < 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!
- Type the following into a file called HelloWorld.js
setTimeout( function() { console.log('World'); }, 2000); console.log('Hello');
- Launch your program in Node and watch in amazement:
node HelloWorld.js
Tuesday, August 2, 2011
Installing Node
Official wiki
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
- Official name is "Node". Unofficial name is "Node.js"
- Written by Ryan Dahl in 2009
- Dahl is employed by Joyent, Node's main sponsor (http://github.com/joyent/node)
What is it?
- server-side JavaScript environment
- runs on top of Google's V8 JavaScript engine (engine in Chrome)
- event-driven I/O - not just web servers, but also things like sockets
Why is it useful?
- it's javascript!
- on the server!
- less resource requirement on the server - does not spawn a new thread for every request. Instead, it allocates resources as needed.
- does not directly block for I/O calls
Who's using it?
- Yammer
- Github
- 37Signals
- Palm/HP (webOs)
- Rdio
- https://github.com/joyent/node/wiki/Projects,-Applications,-and-Companies-Using-Node