intro to:
iain nash
HackSC Series Fall 2013
Github Talk Repo:
Get started:
Install Node.js
http://nodejs.org/
Why is node so hip?
- event-driven
- bridges javascript server + client code
- allows for non-blocking IO
Because it's fast
Because it's easy
javascript is on
the client + the server
easy.
Nonblocking vs Blocking
When making a disk request:
php:
<?php
$big_file = file_get_contents("huge_file.txt");
// ^ blocks process until done
$rows = count_rows($big_file);
echo "There are $rows rows";
node:
fs.readFile('huge_file.txt', function(file_contents){
// adds nonblocking callback, allowing other operations to continue
callback(file_contents.split("\n").length);
}
speed:
Because I/O operations are
tens of millions times
slower than processor time
Real-time apps
Because Node.js is non-blocking, its
well-suited for real-time web applications.
app.route('/poll', function(response){
// can wait a LONG time for the response
// without much processor load, or opening tons of threads
when('message_sent', function(message){
response.setOk();
response.send(message);
}
}
Most web stacks:
Have to use ajax polling:
have any updates? no
have any updates? no
have any updates? no
(repeat 20x...)
have any updates? yes!
Node.JS
Nonblocking + Lightweight (no threads / forks):
have any updates? ......... (20sec) yes! .......... here you go!
No back + forth = allows for realtime communication.
Server? huh?
Most web programming languages use a webserver,
With Node you run it's own webserver.
Make your first node server!
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Run with: node <filename>.js,
then go to: http://localhost:1337/
What's going on here?
var http = require('http');
// ^ here we require node's http library, into the http object
http.createServer(function (req, res) {
// ^ this method is a node api method to create a http server
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
// ^ callback when we get a request, to respond to it asynch.
}).listen(1337, '127.0.0.1');
// ^ calls the listen function of the new node http.Server object.
console.log('Server running at http://127.0.0.1:1337/');
// ^ console.log for debugging outputs to stdout, just like web inspectors on the frontend
Let's add some realtime:
var http = require('http')
, fs = require('fs')
, events = require('events')
, router = require('./router');
// ^ shiny - we're requiring our own local file (./router.js)
var stream = new events.EventEmitter();
var index_html = fs.readFileSync('chatroom.html');
http.createServer(function(req, res){
var test_route = routes[req.method + ':' + req.url.match(/\/([A-Za-z0-9]*)/)[1]];
// :-);
if (!test_route) test_route = routes['GET:404'];
// if not found, 404;
test_route(req, res);
// send to router.
}).listen(1337);
the "router"
module.exports = { // we're exporting these functions
// requiring(this file) - returns the module.exports object.
// AJAX Long Polling Route
"GET:poll": function(req, res){
stream.once('chat', function(message){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(message);
});
},
// Index.html Page
"GET:": function(req, res){
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(index_html);
},
// continued...
Router - part #2
// 404 page :( (called by simple router)
"GET:404": function(req, res){
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end('Page Not Found!');
},
// Message Post Page
"POST:message": function(req, res){
var post_body = '';
req.on('data', function(data){
post_body += data;
});
req.on('end', function(){
stream.emit('chat', post_body);
})
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('ok');
}
}
sounds hard? 'cause it is:
install express:
npm install express
var express = require('express')
, app = express();
// express takes care of the routing, and request/response helpers
app.get('/http.txt', function(req, res){
var body = 'hello world!';
res.setHeader('Content-Type', 'text/plain');
res.setHeader('Content-Length', body.length);
res.end(body);
});
// or have express do more for you:
app.get('/hi.txt', function(req, res){
res.end('hello world!');
});
app.listen(3000);
packages? enter npm
Node Package Manager
usage:
Usage: npm <command> where <command> is one of: init, install, isntall, la, link, list, ll, ln, login, ls, outdated, owner, pack, prefix, prune, publish, r, rb, rebuild, remove, restart, rm, root, run-script, s, se, search, set, show, shrinkwrap, star, start, stop, submodule, tag, test, tst, un, uninstall, unlink, unpublish, unstar, up, update npm <cmd> -h quick help on <cmd> npm -l display full usage info npm faq commonly asked questions npm help <term> search for help on <term> npm help npm involved overview Specify configs in the ini-formatted file: /Users/iain/.npmrc or on the command line via: npm <command> --key value Config info can be viewed via: npm help config npm@1.1.70 /Users/iain/.nvm/v0.8.5/lib/node_modules/npm
Package.json
{
"name": "packagename",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "2.5.5",
"stylus": "0.22.2"
}
}
Official Documentation:
github.com/isaacs/npm/blob/master/doc/files/package.json.md
or:
$ npm help json
Not your mom's javascript:
Common style guidelines:
- 2 spaces for indentation
- braces on the same line as conditional
- var comma initialization
- single quote strings / don't repeat yourself
var fubar = 'hi'
, thing = "that"
, object = {
"bar": "foo"
, "fubar": "asdf"
};
if (thing == 'that'){
do(object);
}
node.js resources
npm packages:
node.js docs:
node.js howtos:
talk repo:
node.js intro
By Iain Nash
node.js intro
- 3,472