Node.js WorkshopTom Hughes-CroucherChief Evangelist / Node Tech Lead@sh1mmertom@joyent.com
Overview•   Introduction•   Why Server-Side JavaScript?•   What is Node?•   Using Node•   Understanding Node•   Node Ecosy...
Introduction• Tom Hughes-Croucher• Chief Evangelist at Joyent• Node.js core contributor• Author of "Up and Running with No...
Scalable Server-Side Code with JavaScriptNode                     Up and Running                        Tom Hughes-Croucher
Major update this week
Why Server-Side  JavaScript?
JavaScriptprogrammers    3>2>1
Massive Code base of jQuery and other JS      libraries
Laziness or “I’m sickof writing stuff twice”I could have said efficiency, but I think we allsecretly long to sit around in...
ProgressiveEnhancement is free*Remember WWCD (What Would Crockford Do)                                    *close enough
TL;DR:SSJS is Awesome Like a Unicorn riding a Narwhal
If SSJS is so   awesomewhy is it "new"?
1. Professionalism
“Yahoo!s corporate motto is: Dont be      eval().“
2. JavaScript Runtimes
Runtimes• V8 (Google), C++• Spider Monkey (Mozilla), C++• Rhino (Mozilla), Java
V8                   Spider                   MonkeyJavaScript Performance
8xSep 08!   Mar 11!
Anatomy of SSJS
Node       {           !
Runtime != Browser
No DOM(By default, anyway)
Summary• Benefits of SSJS • Lots of JavaScript expertise • Lots of web code in JS libraries • Write once, run anywhere • Pr...
What is Node?
Node• JavaScript programming environment• Uses V8 runtime• Event Driven• Non-blocking libraries• Supports CommonJS module ...
Woah! Overload.
1. Its JavaScript
See Above.
2. Its Fast
concurrency=300, Smaller is Better                 400                 300response time (ms)                              ...
3. Its easy to extend
Modules in JSAdd-ons in C
4. Node is _not_ Rails/     Django/etc
Node is bare-bone to     the metal
However, the Nodecommunity are making  Rails/Django/etc
5. Node is young
Stable is "stable"Unstable moves fast
Using Node
Using Node• Part 1. Installation• Part 2. Basics• Part 3. Getting stuck in
Part 1. Installation
Navea.k.a the easy way
Enki:~ $ wget -q http://github.com/isaacs/nave/raw/master/nave.shEnki:~ $ chmod 755 nave.shEnki:~ $ ./nave.sh install latest
Nave• Installs and versions Node• Allows Node shells with specific versions• Allows you to get latest <-- Stable• May add u...
Manual Installation
Go to http://nodejs.org/#downloadand get the URL of the current         stable release
Enki:~ $ wget -q http://nodejs.org/dist/node-v0.4.10.tar.gzEnki:~ $ tar xzf node-v0.4.10.tar.gzEnki:~ $ cd node-v0.4.10Enk...
Local or system?
Local
Enki:~/node-v0.4.10 $ mkdir ~/localEnki:~/node-v0.4.10 $ ./configure --prefix=~/localChecking for program g++ or c++        ...
Enki:~/node-v0.4.10 $ makeWaf: Entering directory `/Users/sh1mmer/node-v0.4.10/buildDEST_OS: darwinDEST_CPU: x86Parallel J...
Enki:~/node-v0.4.10 $ make installWaf: Entering directory `/Users/sh1mmer/node-v0.4.10/buildDEST_OS: darwinDEST_CPU: x86Pa...
Enki:~/node-v0.4.10 $ echo $PATH/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/local/git/bi...
System
Enki:~/node-v0.4.10   $ ./configure...Enki:~/node-v0.4.10   $ make...Enki:~/node-v0.4.10   $ sudo make install...Enki:~/nod...
Exercise• Get Node head from Github using  Git• Install to ~/node
Part 2. Basics
node-replInteractive JavaScript terminal
$Enki:~ $ node
$Enki:~ $ node>3>2>1false> true == 1true> true === 1false
> console.log(Hello World);Hello World> .help.clear Break, and also clear the local context..exit Exit the prompt.help Sho...
Enki:~ $ node> var foo = "bar";> foo;bar> .clearClearing context...> fooReferenceError: foo is not defined   at [object Con...
var http = require(http);http.createServer(function (req, res) {  res.writeHead(200, {Content-Type: text/plain});  res.end...
var http = require(http);//include the http library
http.createServer(function (req, res) {}).listen(8124, "127.0.0.1");//create an http server//when ‘stuff’ happens call thi...
http.createServer(function (req, res) {  res.writeHead(200, {Content-Type: text/plain});  res.end(Hello Worldn);})//when ‘...
console.log(Server running at http://127.0.0.1:8124/);//write Server is running at http://127.0.0.1:8124///to the console
Interactive Debugging
Enki:~/Code/node-examples $ node --debughelloworld.jsdebugger listening on port 5858Server running at http://127.0.0.1:8124/
Enki:~ $ npm install node-inspectornode-inspector@0.1.8 ./node_modules/node-inspector       websocket-server@1.4.04      p...
Exercises• Modify the HTTP server to return the text  "Im learning Node"• Change the HTTP response to HTML and  return you...
Part 3. Getting Stuck In
HTTP Client
var http = require(http);var request = http.request({host: www.google.com,port: 80, path: /, method:GET});request.on(respo...
Streaming API
write(data)               write(data)       DestinationRequest                  end()         (google.com)            resp...
Exercise• Fetch the NYTimes.com and output  the contents to the console• Create a web server • Create an HTTP client • POS...
Events
object.on(event, function() {  //stuff} );
EventEmitter
EventEmitter• manage "event handlers" • list of functions to be called per    event• provide mechanism to trigger  events
var util = require(util),  EE = require(events).EventEmitter;util.inherits(MyClass, EE);var myObj = new MyClass();//nb usi...
exports.inherits = function (ctor, superCtor) {   ctor.super_ = superCtor;   ctor.prototype = Object.create(superCtor.prot...
More than just core
CommonJS Modules
Library format for       SSJS
math.jsexports.add = function() {   var sum = 0, i = 0, args = arguments, l = args.length;   while (i < l) {      sum += a...
Protipexports.awesome = function() {  //yay my code is awesomesauce};var exports.fail = function() {  //exports is a globa...
Exercise• Create a CommonJS module called "fish" • Provide functions to:   • swim   • mouth breath   • flop around• Import y...
Node PackageManager (NPM)
NPM is written inJavaScript for Node
Enki:~ $ cat `which npm`#!/usr/bin/env node;(function () { // wrapper in case were in module_context modevar log = require...
Enki:~/Code/node(master) $ npm install expressexpress@2.3.11 ../../node_modules/express       mime@1.2.2      connect@1.4....
Yay. Easy.
Install instructions  https://github.com/isaacs/npm
Express.js
Sinatra Style MVC   framework
var app = require(express).createServer();app.get(/, function(req, res){    res.send(hello world);});app.listen(3000);
HTTP Verb Oriented
Middleware
app.use(express.bodyParser());app.use(express.cookieParser());app.post(/, function(req, res){  // Perhaps we posted severa...
Templating
var express = require("express");app.configure(function () {     var public = __dirname + "/../public/";     public = requi...
Exercise• Create an Express server• Serve two different pages based on  value of the HTTP Get param "page"• Create a redir...
Express in depth
Routes• Routes are based on verbs • GET • POST • PUT • DELETE • ALL (not a real verb, but obvious)
Simple routes
app.get(‘/’, function(req,res) {  res.send(‘hello root’);});
Routes with variables
app.get(‘/user/:id’, function(req,res) {  res.send(‘hello ‘ + req.params.id);});
Optional flags in     routes
app.get(‘/:filename?’, function(req,res) {  if(req.params.filename) {    res.send(req.params.filename);  } else {    res.send...
Regex as routes
app.get(///, function(req, res) {  //like using ‘/’ ?  res.send(‘/’);});
app.get(/^/d+/?$/, function(req,res) {  res.send(‘matches a number’);});
app.get(/^/(.+)/?$/, function(req,res) {  //note translation of %23, etc  res.send(‘Got: ’ + req.params[0]); //also captur...
Using regex todefine parameters
app.get(‘/index.:format((html|json))’,function(req,res) {  res.send(Got:  + req.params.format);});
app.get(/:id(d+), function(req,res) {  //only digits, right?  res.send(req.params.id);});
app.get(/:id(d+), function(req,res) {  //escape your  in strings  res.send(req.params.id);});
Routing magic:                Router.jsfunction normalizePath(path, keys) {  path = path   .concat(/?)   .replace(//(/g, (...
Routing magic•   If . before :variable? then . is also optional•   If ? is not after a variable then only the previous cha...
Exercises•   Create an express app with routes that capture /    /products and /services•   Create a route that captures t...
Passing Control• Routes are actually stacked middleware• You can pass control between routes• The next() function calls th...
app.get(/users/:id, function(req, res, next){ var id = req.params.id;  if (checkPermission(id)) {    // show private page ...
Passing Control•   next() is a function of router (and defined in the    closure containing the route)•   router will grab ...
Exercises• Create a simple check for correct product  IDs if not pass control to a route showing a  custom error page• Use...
Middleware
Its a pattern
req, resnext()next()next()
req, resnext()next()                    Dispatchernext()                 req                       res
req, res, next
var express = require(express),  app = express.createServer();var middleware = function (req, res, next) {  req.foo = bar;...
var express = require(express),  app = express.createServer();var middleware = function (req, res, next) {  var send = res...
Connect middleware    (Renamed express.* for convenience)•   logger            •   profiler•   bodyParser        •   respon...
var express = require(express),  app = express.createServer();app.use(express.logger());app.use(express.bodyParser());app....
Ordering matters
Router uses "internalmiddleware"
var express = require(express),  app = express.createServer();var middleware = function (req, res, next) {  req.foo = bar;...
var a, b, c, d;a = b = c = d = function(req,res,next) {  next();}var set1 = [a,b];var set2 = [c,d];var all = [set1, set2];...
Middleware factories
Middleware are just    functions
var a, b, c, d;a = b = c = d = function(req,res,next) {  next();}var set1 = [a,b];var set2 = [c,d];var all = [set1, set2];...
var mFactory = function(letter) {  return function(req,res,next) {    var send = res.send;    res.send = function(d) {    ...
Exercise• Create a middleware to detect mobile  phone browsers and attach a boolean to  req• Create an express app that se...
Error handling
function NotFound(msg){  this.name = NotFound;  Error.call(this, msg);  Error.captureStackTrace(this, arguments.callee);}N...
app.error(function(err, req, res, next){    if (err instanceof NotFound) {        res.render(404.jade);    } else {       ...
View Rendering
app.get(/, function(req, res){    res.render(index.ejs, { title: Falsy Demo });});
Enki:~/Code/express-demo $ tree.       app.js      lib      public      views            index.ejs            layout.ejs  ...
Dont forget to           installnpm install ejsnpm install jade
layout.ejs<!DOCTYPE html><html lang="en">  <head>   <meta charset="utf-8">   <title><%= title %></title>  </head>  <body> ...
• layout is a framework unless you  turn it off• body is a special variable for layout  referring to the file specified
app.set(view engine, ejs);app.get(/, function(req,res) {  res.render(index, { title:Falsy Demo});});
//globalapp.set(view options), {  layout: false;});//or per routeres.render(index, {layout: false});
Partial views
View Partials• Repeating elements• Take a collection• Iterate over the collection• "Built in" variables for managing  coll...
layout.ejs<!DOCTYPE html><html lang="en">  <head>   <meta charset="utf-8">   <%- partial(stylesheet, stylesheets) %>   <ti...
partials/stylesheet.ejs<link rel="stylesheet" type="text/css" href="<%-stylesheet %>">
res.render(index, {  locals: {title: title,        header: header,        content: content,        stylesheets: [/public/s...
Exercises•   Create an express server that use jade, haml, ejs to    render an index page•   Create a public folder and in...
Questions
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
Upcoming SlideShare
Loading in …5
×

OSCON 2011 - Node.js Tutorial

15,022
-1

Published on

Published in: Technology
2 Comments
55 Likes
Statistics
Notes
No Downloads
Views
Total Views
15,022
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
657
Comments
2
Likes
55
Embeds 0
No embeds

No notes for slide
  • \n
  • Running order\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Service behind traffic server\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • OSCON 2011 - Node.js Tutorial

    1. 1. Node.js WorkshopTom Hughes-CroucherChief Evangelist / Node Tech Lead@sh1mmertom@joyent.com
    2. 2. Overview• Introduction• Why Server-Side JavaScript?• What is Node?• Using Node• Understanding Node• Node Ecosystem• Programming Style• More Complex applications• Deploying Node apps to the cloud
    3. 3. Introduction• Tom Hughes-Croucher• Chief Evangelist at Joyent• Node.js core contributor• Author of "Up and Running with Node.js"
    4. 4. Scalable Server-Side Code with JavaScriptNode Up and Running Tom Hughes-Croucher
    5. 5. Major update this week
    6. 6. Why Server-Side JavaScript?
    7. 7. JavaScriptprogrammers 3>2>1
    8. 8. Massive Code base of jQuery and other JS libraries
    9. 9. Laziness or “I’m sickof writing stuff twice”I could have said efficiency, but I think we allsecretly long to sit around in our underwear.
    10. 10. ProgressiveEnhancement is free*Remember WWCD (What Would Crockford Do) *close enough
    11. 11. TL;DR:SSJS is Awesome Like a Unicorn riding a Narwhal
    12. 12. If SSJS is so awesomewhy is it "new"?
    13. 13. 1. Professionalism
    14. 14. “Yahoo!s corporate motto is: Dont be eval().“
    15. 15. 2. JavaScript Runtimes
    16. 16. Runtimes• V8 (Google), C++• Spider Monkey (Mozilla), C++• Rhino (Mozilla), Java
    17. 17. V8 Spider MonkeyJavaScript Performance
    18. 18. 8xSep 08! Mar 11!
    19. 19. Anatomy of SSJS
    20. 20. Node { !
    21. 21. Runtime != Browser
    22. 22. No DOM(By default, anyway)
    23. 23. Summary• Benefits of SSJS • Lots of JavaScript expertise • Lots of web code in JS libraries • Write once, run anywhere • Progressive Enhancement• Why SSJS happened now • Professionalism in JavaScript • New generation of JavaScript runtimes
    24. 24. What is Node?
    25. 25. Node• JavaScript programming environment• Uses V8 runtime• Event Driven• Non-blocking libraries• Supports CommonJS module format• Supports C/C++ based add-ons
    26. 26. Woah! Overload.
    27. 27. 1. Its JavaScript
    28. 28. See Above.
    29. 29. 2. Its Fast
    30. 30. concurrency=300, Smaller is Better 400 300response time (ms) server nginx 200 thin tornado node_buffer 100 24 26 28 210 212 214 216 218 response size (bytes)
    31. 31. 3. Its easy to extend
    32. 32. Modules in JSAdd-ons in C
    33. 33. 4. Node is _not_ Rails/ Django/etc
    34. 34. Node is bare-bone to the metal
    35. 35. However, the Nodecommunity are making Rails/Django/etc
    36. 36. 5. Node is young
    37. 37. Stable is "stable"Unstable moves fast
    38. 38. Using Node
    39. 39. Using Node• Part 1. Installation• Part 2. Basics• Part 3. Getting stuck in
    40. 40. Part 1. Installation
    41. 41. Navea.k.a the easy way
    42. 42. Enki:~ $ wget -q http://github.com/isaacs/nave/raw/master/nave.shEnki:~ $ chmod 755 nave.shEnki:~ $ ./nave.sh install latest
    43. 43. Nave• Installs and versions Node• Allows Node shells with specific versions• Allows you to get latest <-- Stable• May add unstable option in future
    44. 44. Manual Installation
    45. 45. Go to http://nodejs.org/#downloadand get the URL of the current stable release
    46. 46. Enki:~ $ wget -q http://nodejs.org/dist/node-v0.4.10.tar.gzEnki:~ $ tar xzf node-v0.4.10.tar.gzEnki:~ $ cd node-v0.4.10Enki:~/node-v0.4.10 $
    47. 47. Local or system?
    48. 48. Local
    49. 49. Enki:~/node-v0.4.10 $ mkdir ~/localEnki:~/node-v0.4.10 $ ./configure --prefix=~/localChecking for program g++ or c++ : /usr/bin/g++Checking for program cpp : /usr/bin/cpp...Checking for fdatasync(2) with c++ : noconfigure finished successfully (3.466s)
    50. 50. Enki:~/node-v0.4.10 $ makeWaf: Entering directory `/Users/sh1mmer/node-v0.4.10/buildDEST_OS: darwinDEST_CPU: x86Parallel Jobs: 1[ 1/69] cc: deps/libeio/eio.c -> build/default/deps/libeio/eio_1.o/usr/bin/gcc -rdynamic -D_GNU_SOURCE -DHAVE_CONFIG_H=1-DEV_MULTIPLICITY=0 -pthread -g -O3 -DHAVE_OPENSSL=1 -DX_STACKSIZE=65536 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_FDATASYNC=0 -DPLATFORM="darwin" -DNDEBUG -Idefault/deps/libeio -I../deps/libeio -Idefault -I.. ../deps/libeio/eio.c -c -o default/deps/libeio/eio_1.o...
    51. 51. Enki:~/node-v0.4.10 $ make installWaf: Entering directory `/Users/sh1mmer/node-v0.4.10/buildDEST_OS: darwinDEST_CPU: x86Parallel Jobs: 1* installing build/default/config.h as /Users/sh1mmer/local/include/node/config.h* installing build/default/node as /Users/sh1mmer/local/bin/node* installing build/default/src/node_config.h as /Users/sh1mmer/local/include/node/node_config.hWaf: Leaving directory `/Users/sh1mmer/node-v0.4.10/buildinstall finished successfully (0.373s)Enki:~/node-v0.4.7 $
    52. 52. Enki:~/node-v0.4.10 $ echo $PATH/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/local/git/bin:/Users/croucher/Code/narwhal/bin:/opt/local/bin:/usr/local/git/bin:/Users/sh1mmer/binEnki:~/node-v0.4.10 $ node -v-bash: node: command not foundEnki:~/node-v0.4.10 $ echo PATH=~/local/bin:$PATH>> ~/.profileEnki:~/node-v0.4.10 $ node -vv0.4.10
    53. 53. System
    54. 54. Enki:~/node-v0.4.10 $ ./configure...Enki:~/node-v0.4.10 $ make...Enki:~/node-v0.4.10 $ sudo make install...Enki:~/node-v0.4.10 $ node -vv0.4.7Enki:~/node-v0.4.10 $
    55. 55. Exercise• Get Node head from Github using Git• Install to ~/node
    56. 56. Part 2. Basics
    57. 57. node-replInteractive JavaScript terminal
    58. 58. $Enki:~ $ node
    59. 59. $Enki:~ $ node>3>2>1false> true == 1true> true === 1false
    60. 60. > console.log(Hello World);Hello World> .help.clear Break, and also clear the local context..exit Exit the prompt.help Show repl options> .clearClearing context...> .exitEnki:~ $
    61. 61. Enki:~ $ node> var foo = "bar";> foo;bar> .clearClearing context...> fooReferenceError: foo is not defined at [object Context]:1:1 at Interface.<anonymous> (repl:98:19) at Interface.emit (events:27:15) at Interface._ttyWrite (readline:295:12) at Interface.write (readline:132:30) at Stream.<anonymous> (repl:79:9) at Stream.emit (events:27:15) at IOWatcher.callback (net:489:16)
    62. 62. var http = require(http);http.createServer(function (req, res) { res.writeHead(200, {Content-Type: text/plain}); res.end(Hello Worldn);}).listen(8124, "127.0.0.1");console.log(Server running at http://127.0.0.1:8124/);
    63. 63. var http = require(http);//include the http library
    64. 64. http.createServer(function (req, res) {}).listen(8124, "127.0.0.1");//create an http server//when ‘stuff’ happens call this anonymous function//listen on port 8124 of the IP 127.0.0.1
    65. 65. http.createServer(function (req, res) { res.writeHead(200, {Content-Type: text/plain}); res.end(Hello Worldn);})//when ‘stuff’ happens my function fires//I get a request object and a response object//I write to the response object header//HTTP status 200 and content-type ‘text/plain’//close the response with the body://Hello World
    66. 66. console.log(Server running at http://127.0.0.1:8124/);//write Server is running at http://127.0.0.1:8124///to the console
    67. 67. Interactive Debugging
    68. 68. Enki:~/Code/node-examples $ node --debughelloworld.jsdebugger listening on port 5858Server running at http://127.0.0.1:8124/
    69. 69. Enki:~ $ npm install node-inspectornode-inspector@0.1.8 ./node_modules/node-inspector websocket-server@1.4.04 paperboy@0.0.2Enki:~ $ node-inspectorvisit http://0.0.0.0:8080/debug?port=5858 to startdebugging
    70. 70. Exercises• Modify the HTTP server to return the text "Im learning Node"• Change the HTTP response to HTML and return your text in an HTML page• Return the User-Agent string from the browser as part of your HTML page• Return different textual responses to 2 (or more) browsers
    71. 71. Part 3. Getting Stuck In
    72. 72. HTTP Client
    73. 73. var http = require(http);var request = http.request({host: www.google.com,port: 80, path: /, method:GET});request.on(response, function (response) { console.log(STATUS: + response.statusCode); console.log(HEADERS: +JSON.stringify(response.headers)); response.setEncoding(utf8); response.on(data, function (chunk) { console.log(BODY: + chunk); });
    74. 74. Streaming API
    75. 75. write(data) write(data) DestinationRequest end() (google.com) response(headers) data(chunk) data(chunk) Response data(chunk) end()
    76. 76. Exercise• Fetch the NYTimes.com and output the contents to the console• Create a web server • Create an HTTP client • POST data to your web server • Output the POST data to console
    77. 77. Events
    78. 78. object.on(event, function() { //stuff} );
    79. 79. EventEmitter
    80. 80. EventEmitter• manage "event handlers" • list of functions to be called per event• provide mechanism to trigger events
    81. 81. var util = require(util), EE = require(events).EventEmitter;util.inherits(MyClass, EE);var myObj = new MyClass();//nb using first class functionsmyObj.on(something, function);
    82. 82. exports.inherits = function (ctor, superCtor) { ctor.super_ = superCtor; ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false } });};
    83. 83. More than just core
    84. 84. CommonJS Modules
    85. 85. Library format for SSJS
    86. 86. math.jsexports.add = function() { var sum = 0, i = 0, args = arguments, l = args.length; while (i < l) { sum += args[i++]; } return sum;};increment.jsvar add = require(math).add;exports.increment = function(val) { return add(val, 1);};var inc = require(increment).increment;var a = 1;inc(a); // 2
    87. 87. Protipexports.awesome = function() { //yay my code is awesomesauce};var exports.fail = function() { //exports is a global //by redeclaring it as //a local variable //your code _will_ fail};
    88. 88. Exercise• Create a CommonJS module called "fish" • Provide functions to: • swim • mouth breath • flop around• Import your module into a node project• Call the various functions
    89. 89. Node PackageManager (NPM)
    90. 90. NPM is written inJavaScript for Node
    91. 91. Enki:~ $ cat `which npm`#!/usr/bin/env node;(function () { // wrapper in case were in module_context modevar log = require("../lib/utils/log")log.waitForConfig()log.info("ok", "it worked if it ends with")var fs = require("../lib/utils/graceful-fs") , path = require("path") , sys = require("../lib/utils/sys") , npm = require("../npm") , ini = require("../lib/utils/ini") , rm = require("../lib/utils/rm-rf")
    92. 92. Enki:~/Code/node(master) $ npm install expressexpress@2.3.11 ../../node_modules/express mime@1.2.2 connect@1.4.2 qs@0.1.0Enki:~/Code/node(master) $
    93. 93. Yay. Easy.
    94. 94. Install instructions https://github.com/isaacs/npm
    95. 95. Express.js
    96. 96. Sinatra Style MVC framework
    97. 97. var app = require(express).createServer();app.get(/, function(req, res){ res.send(hello world);});app.listen(3000);
    98. 98. HTTP Verb Oriented
    99. 99. Middleware
    100. 100. app.use(express.bodyParser());app.use(express.cookieParser());app.post(/, function(req, res){ // Perhaps we posted several items with a form // (use the bodyParser() middleware for this) var items = req.body.items; console.log(items); res.send(logging);});
    101. 101. Templating
    102. 102. var express = require("express");app.configure(function () { var public = __dirname + "/../public/"; public = require("path").normalize(public); app.set("views", __dirname + "/views"); app.set("view engine", "jade");});app.get("/", function (req, res) { res.render("index", { locals : { h1: Router Stats, scripts : [ "/public/smoothie.js", "/public/raphael.js", "/public/base.js", "/public/gfx.js", "/public/explore.js", "/public/app.js" ] } }});
    103. 103. Exercise• Create an Express server• Serve two different pages based on value of the HTTP Get param "page"• Create a redirect from /old to /new• Set a cookie on the client
    104. 104. Express in depth
    105. 105. Routes• Routes are based on verbs • GET • POST • PUT • DELETE • ALL (not a real verb, but obvious)
    106. 106. Simple routes
    107. 107. app.get(‘/’, function(req,res) { res.send(‘hello root’);});
    108. 108. Routes with variables
    109. 109. app.get(‘/user/:id’, function(req,res) { res.send(‘hello ‘ + req.params.id);});
    110. 110. Optional flags in routes
    111. 111. app.get(‘/:filename?’, function(req,res) { if(req.params.filename) { res.send(req.params.filename); } else { res.send(‘root’); }});
    112. 112. Regex as routes
    113. 113. app.get(///, function(req, res) { //like using ‘/’ ? res.send(‘/’);});
    114. 114. app.get(/^/d+/?$/, function(req,res) { res.send(‘matches a number’);});
    115. 115. app.get(/^/(.+)/?$/, function(req,res) { //note translation of %23, etc res.send(‘Got: ’ + req.params[0]); //also captures become an array});
    116. 116. Using regex todefine parameters
    117. 117. app.get(‘/index.:format((html|json))’,function(req,res) { res.send(Got: + req.params.format);});
    118. 118. app.get(/:id(d+), function(req,res) { //only digits, right? res.send(req.params.id);});
    119. 119. app.get(/:id(d+), function(req,res) { //escape your in strings res.send(req.params.id);});
    120. 120. Routing magic: Router.jsfunction normalizePath(path, keys) { path = path .concat(/?) .replace(//(/g, (?:/) .replace(/(/)?(.)?:(w+)(?:((.*?)))?(?)?/g, function(_, slash, format, key,capture, optional){ keys.push(key); slash = slash || ; return + (optional ? : slash) + (?: + (optional ? slash : ) + (format || ) + (capture || ([^/]+?)) + ) + (optional || ); }) .replace(/([/.])/g, $1) .replace(/*/g, (.+)); return new RegExp(^ + path + $, i);}
    121. 121. Routing magic• If . before :variable? then . is also optional• If ? is not after a variable then only the previous character is affected• / at the end of URLs automatically optional• * Can be used as a wildcard in routes• Includes when end of URL is optional e.g. /app/e?• Regex can be used any place in a route string e.g. /app/(d)r?
    122. 122. Exercises• Create an express app with routes that capture / /products and /services• Create a route that captures the product ID after /product/ e.g. /product/abc12 and returns it in the response• Use a regular expression to restrict the ID parameter to 3 letter followed by 3-5 numbers• Create a route using a regex that matches the entire route
    123. 123. Passing Control• Routes are actually stacked middleware• You can pass control between routes• The next() function calls the next matching route
    124. 124. app.get(/users/:id, function(req, res, next){ var id = req.params.id; if (checkPermission(id)) { // show private page } else { next(); }});app.get(/users/:id, function(req, res){ // show public user page});
    125. 125. Passing Control• next() is a function of router (and defined in the closure containing the route)• router will grab routes in the order they were declared• e.g. since/* will match everything so it should be the last route!• router doesnt care about verbs so you can use all() to operate on all verbs/routes and then use next() to pass to get(), put(), etc
    126. 126. Exercises• Create a simple check for correct product IDs if not pass control to a route showing a custom error page• Use app.all() to check user permission before showing (mock-up) edit controls on a web site
    127. 127. Middleware
    128. 128. Its a pattern
    129. 129. req, resnext()next()next()
    130. 130. req, resnext()next() Dispatchernext() req res
    131. 131. req, res, next
    132. 132. var express = require(express), app = express.createServer();var middleware = function (req, res, next) { req.foo = bar; next();};app.use(middleware);app.get(/, function(req, res) { res.send(req.foo);
    133. 133. var express = require(express), app = express.createServer();var middleware = function (req, res, next) { var send = res.send; res.send = function(d) { res.send = send; res.send(hijacked! + d); } next();};app.use(middleware);app.get(/, function(req, res) { res.send(hi);});
    134. 134. Connect middleware (Renamed express.* for convenience)• logger • profiler• bodyParser • responseTime• cookieParser • basicAuth• session • favicon• static • vhost• errorHandler
    135. 135. var express = require(express), app = express.createServer();app.use(express.logger());app.use(express.bodyParser());app.use(express.cookieParser());app.use(app.router);app.use(express.static(__dirname + /images));app.use(express.errorHandler());app.get(/, function(req, res) { res.send(<html><img src="/image.png"></html);});app.listen(9003);
    136. 136. Ordering matters
    137. 137. Router uses "internalmiddleware"
    138. 138. var express = require(express), app = express.createServer();var middleware = function (req, res, next) { req.foo = bar; next();};app.get(/, middleware, function(req, res) { res.send(req.foo);});
    139. 139. var a, b, c, d;a = b = c = d = function(req,res,next) { next();}var set1 = [a,b];var set2 = [c,d];var all = [set1, set2];app.get(/set1, set1, function(req,res) { res.send(output);});app.get(/set2, [c,d], function(req,res) { res.send(output);});app.get(/all, all, function(req,res) { res.send(output);});
    140. 140. Middleware factories
    141. 141. Middleware are just functions
    142. 142. var a, b, c, d;a = b = c = d = function(req,res,next) { next();}var set1 = [a,b];var set2 = [c,d];var all = [set1, set2];app.get(/set1, set1, function(req,res) { res.send(output);});app.get(/set2, [c,d], function(req,res) { res.send(output);});app.get(/all, all, function(req,res) { res.send(output);});
    143. 143. var mFactory = function(letter) { return function(req,res,next) { var send = res.send; res.send = function(d) { res.send = send; res.send(letter + + d); } next(); }};var set1 = [mFactory(a),mFactory(b)];var set2 = [mFactory(c),mFactory(d)];var all = [set1, set2];app.get(/set1, set1, function(req,res) { res.send(output);});app.get(/set2, set2, function(req,res) { res.send(output);});app.get(/all, all, function(req,res) { res.send(output);});
    144. 144. Exercise• Create a middleware to detect mobile phone browsers and attach a boolean to req• Create an express app that serves up links to an image using staticProvider• Modify Profiler to profile your app and write each profile to a log file• Create a middleware factory that sets the HTTP Expires header based on roles
    145. 145. Error handling
    146. 146. function NotFound(msg){ this.name = NotFound; Error.call(this, msg); Error.captureStackTrace(this, arguments.callee);}NotFound.prototype.__proto__ = Error.prototype;app.get(/404, function(req, res){ throw new NotFound;});app.get(/500, function(req, res){ throw new Error(keyboard cat!);});
    147. 147. app.error(function(err, req, res, next){ if (err instanceof NotFound) { res.render(404.jade); } else { next(err); }});
    148. 148. View Rendering
    149. 149. app.get(/, function(req, res){ res.render(index.ejs, { title: Falsy Demo });});
    150. 150. Enki:~/Code/express-demo $ tree. app.js lib public views index.ejs layout.ejs layout1.ejs partials stylesheet.ejs4 directories, 5 filesEnki:~/Code/express-demo $
    151. 151. Dont forget to installnpm install ejsnpm install jade
    152. 152. layout.ejs<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <title><%= title %></title> </head> <body> <%- body %> </body></html>
    153. 153. • layout is a framework unless you turn it off• body is a special variable for layout referring to the file specified
    154. 154. app.set(view engine, ejs);app.get(/, function(req,res) { res.render(index, { title:Falsy Demo});});
    155. 155. //globalapp.set(view options), { layout: false;});//or per routeres.render(index, {layout: false});
    156. 156. Partial views
    157. 157. View Partials• Repeating elements• Take a collection• Iterate over the collection• "Built in" variables for managing collections
    158. 158. layout.ejs<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <%- partial(stylesheet, stylesheets) %> <title><%= title %></title> </head> <body> <h1><%= header %></h1> <%- body %> </body></html>
    159. 159. partials/stylesheet.ejs<link rel="stylesheet" type="text/css" href="<%-stylesheet %>">
    160. 160. res.render(index, { locals: {title: title, header: header, content: content, stylesheets: [/public/style.css] }, });
    161. 161. Exercises• Create an express server that use jade, haml, ejs to render an index page• Create a public folder and include file from it (CSS, images, etc) in your layout• Create a route for /blog/id to accept only digits• Make a fake database (array) of blog posts and use a middleware to validate each id is valid• Create a view for the /blog/id show the correct post• Use a view partial to a preview of each blog post on the index page
    162. 162. Questions
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×